1238106Sdes/*
2238106Sdes * services/outside_network.h - listen to answers from the network
3238106Sdes *
4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved.
5238106Sdes *
6238106Sdes * This software is open source.
7238106Sdes *
8238106Sdes * Redistribution and use in source and binary forms, with or without
9238106Sdes * modification, are permitted provided that the following conditions
10238106Sdes * are met:
11238106Sdes *
12238106Sdes * Redistributions of source code must retain the above copyright notice,
13238106Sdes * this list of conditions and the following disclaimer.
14238106Sdes *
15238106Sdes * Redistributions in binary form must reproduce the above copyright notice,
16238106Sdes * this list of conditions and the following disclaimer in the documentation
17238106Sdes * and/or other materials provided with the distribution.
18238106Sdes *
19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may
20238106Sdes * be used to endorse or promote products derived from this software without
21238106Sdes * specific prior written permission.
22238106Sdes *
23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24266114Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25266114Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26266114Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27266114Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28266114Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29266114Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30266114Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31266114Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32266114Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33266114Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34238106Sdes */
35238106Sdes
36238106Sdes/**
37238106Sdes * \file
38238106Sdes *
39238106Sdes * This file has functions to send queries to authoritative servers,
40238106Sdes * and wait for the pending answer, with timeouts.
41238106Sdes */
42238106Sdes
43238106Sdes#ifndef OUTSIDE_NETWORK_H
44238106Sdes#define OUTSIDE_NETWORK_H
45238106Sdes
46238106Sdes#include "util/rbtree.h"
47238106Sdes#include "util/netevent.h"
48276605Sdes#include "dnstap/dnstap_config.h"
49238106Sdesstruct pending;
50238106Sdesstruct pending_timeout;
51238106Sdesstruct ub_randstate;
52238106Sdesstruct pending_tcp;
53238106Sdesstruct waiting_tcp;
54238106Sdesstruct waiting_udp;
55368693Scystruct reuse_tcp;
56238106Sdesstruct infra_cache;
57238106Sdesstruct port_comm;
58238106Sdesstruct port_if;
59266114Sdesstruct sldns_buffer;
60276605Sdesstruct serviced_query;
61276605Sdesstruct dt_env;
62307729Sdesstruct edns_option;
63356345Scystruct module_env;
64356345Scystruct module_qstate;
65356345Scystruct query_info;
66238106Sdes
67238106Sdes/**
68238106Sdes * Send queries to outside servers and wait for answers from servers.
69238106Sdes * Contains answer-listen sockets.
70238106Sdes */
71238106Sdesstruct outside_network {
72238106Sdes	/** Base for select calls */
73238106Sdes	struct comm_base* base;
74238106Sdes	/** pointer to time in seconds */
75266114Sdes	time_t* now_secs;
76238106Sdes	/** pointer to time in microseconds */
77238106Sdes	struct timeval* now_tv;
78238106Sdes
79238106Sdes	/** buffer shared by UDP connections, since there is only one
80238106Sdes	    datagram at any time. */
81266114Sdes	struct sldns_buffer* udp_buff;
82238106Sdes	/** serviced_callbacks malloc overhead when processing multiple
83238106Sdes	 * identical serviced queries to the same server. */
84238106Sdes	size_t svcd_overhead;
85238106Sdes	/** use x20 bits to encode additional ID random bits */
86238106Sdes	int use_caps_for_id;
87238106Sdes	/** outside network wants to quit. Stop queued msgs from sent. */
88238106Sdes	int want_to_quit;
89238106Sdes
90238106Sdes	/** number of unwanted replies received (for statistics) */
91238106Sdes	size_t unwanted_replies;
92238106Sdes	/** cumulative total of unwanted replies (for defense) */
93238106Sdes	size_t unwanted_total;
94238106Sdes	/** threshold when to take defensive action. If 0 then never. */
95238106Sdes	size_t unwanted_threshold;
96238106Sdes	/** what action to take, called when defensive action is needed */
97238106Sdes	void (*unwanted_action)(void*);
98238106Sdes	/** user param for action */
99238106Sdes	void* unwanted_param;
100238106Sdes
101238106Sdes	/** linked list of available commpoints, unused file descriptors,
102238106Sdes	 * for use as outgoing UDP ports. cp.fd=-1 in them. */
103238106Sdes	struct port_comm* unused_fds;
104238106Sdes	/** if udp is done */
105238106Sdes	int do_udp;
106266114Sdes	/** if udp is delay-closed (delayed answers do not meet closed port)*/
107266114Sdes	int delayclose;
108266114Sdes	/** timeout for delayclose */
109266114Sdes	struct timeval delay_tv;
110368693Scy	/** if we perform udp-connect, connect() for UDP socket to mitigate
111368693Scy	 * ICMP side channel leakage */
112368693Scy	int udp_connect;
113238106Sdes
114238106Sdes	/** array of outgoing IP4 interfaces */
115238106Sdes	struct port_if* ip4_ifs;
116238106Sdes	/** number of outgoing IP4 interfaces */
117238106Sdes	int num_ip4;
118238106Sdes
119238106Sdes	/** array of outgoing IP6 interfaces */
120238106Sdes	struct port_if* ip6_ifs;
121238106Sdes	/** number of outgoing IP6 interfaces */
122238106Sdes	int num_ip6;
123238106Sdes
124238106Sdes	/** pending udp queries waiting to be sent out, waiting for fd */
125238106Sdes	struct pending* udp_wait_first;
126238106Sdes	/** last pending udp query in list */
127238106Sdes	struct pending* udp_wait_last;
128238106Sdes
129238106Sdes	/** pending udp answers. sorted by id, addr */
130356345Scy	rbtree_type* pending;
131238106Sdes	/** serviced queries, sorted by qbuf, addr, dnssec */
132356345Scy	rbtree_type* serviced;
133238106Sdes	/** host cache, pointer but not owned by outnet. */
134238106Sdes	struct infra_cache* infra;
135238106Sdes	/** where to get random numbers */
136238106Sdes	struct ub_randstate* rnd;
137238106Sdes	/** ssl context to create ssl wrapped TCP with DNS connections */
138238106Sdes	void* sslctx;
139366095Scy	/** if SNI will be used for TLS connections */
140366095Scy	int tls_use_sni;
141276605Sdes#ifdef USE_DNSTAP
142276605Sdes	/** dnstap environment */
143276605Sdes	struct dt_env* dtenv;
144276605Sdes#endif
145296415Sdes	/** maximum segment size of tcp socket */
146296415Sdes	int tcp_mss;
147366095Scy	/** IP_TOS socket option requested on the sockets */
148366095Scy	int ip_dscp;
149238106Sdes
150238106Sdes	/**
151238106Sdes	 * Array of tcp pending used for outgoing TCP connections.
152238106Sdes	 * Each can be used to establish a TCP connection with a server.
153238106Sdes	 * The file descriptors are -1 if they are free, and need to be
154238106Sdes	 * opened for the tcp connection. Can be used for ip4 and ip6.
155238106Sdes	 */
156238106Sdes	struct pending_tcp **tcp_conns;
157238106Sdes	/** number of tcp communication points. */
158238106Sdes	size_t num_tcp;
159276605Sdes	/** number of tcp communication points in use. */
160276605Sdes	size_t num_tcp_outgoing;
161368693Scy	/**
162368693Scy	 * tree of still-open and waiting tcp connections for reuse.
163368693Scy	 * can be closed and reopened to get a new tcp connection.
164368693Scy	 * or reused to the same destination again.  with timeout to close.
165368693Scy	 * Entries are of type struct reuse_tcp.
166368693Scy	 * The entries are both active and empty connections.
167368693Scy	 */
168368693Scy	rbtree_type tcp_reuse;
169368693Scy	/** max number of tcp_reuse entries we want to keep open */
170368693Scy	size_t tcp_reuse_max;
171368693Scy	/** first and last(oldest) in lru list of reuse connections.
172368693Scy	 * the oldest can be closed to get a new free pending_tcp if needed
173368693Scy	 * The list contains empty connections, that wait for timeout or
174368693Scy	 * a new query that can use the existing connection. */
175368693Scy	struct reuse_tcp* tcp_reuse_first, *tcp_reuse_last;
176238106Sdes	/** list of tcp comm points that are free for use */
177238106Sdes	struct pending_tcp* tcp_free;
178238106Sdes	/** list of tcp queries waiting for a buffer */
179238106Sdes	struct waiting_tcp* tcp_wait_first;
180238106Sdes	/** last of waiting query list */
181238106Sdes	struct waiting_tcp* tcp_wait_last;
182238106Sdes};
183238106Sdes
184238106Sdes/**
185238106Sdes * Outgoing interface. Ports available and currently used are tracked
186238106Sdes * per interface
187238106Sdes */
188238106Sdesstruct port_if {
189238106Sdes	/** address ready to allocate new socket (except port no). */
190238106Sdes	struct sockaddr_storage addr;
191238106Sdes	/** length of addr field */
192238106Sdes	socklen_t addrlen;
193238106Sdes
194307729Sdes	/** prefix length of network address (in bits), for randomisation.
195307729Sdes	 * if 0, no randomisation. */
196307729Sdes	int pfxlen;
197307729Sdes
198366095Scy#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
199238106Sdes	/** the available ports array. These are unused.
200238106Sdes	 * Only the first total-inuse part is filled. */
201238106Sdes	int* avail_ports;
202238106Sdes	/** the total number of available ports (size of the array) */
203238106Sdes	int avail_total;
204366095Scy#endif
205238106Sdes
206238106Sdes	/** array of the commpoints currently in use.
207238106Sdes	 * allocated for max number of fds, first part in use. */
208238106Sdes	struct port_comm** out;
209238106Sdes	/** max number of fds, size of out array */
210238106Sdes	int maxout;
211238106Sdes	/** number of commpoints (and thus also ports) in use */
212238106Sdes	int inuse;
213238106Sdes};
214238106Sdes
215238106Sdes/**
216238106Sdes * Outgoing commpoint for UDP port.
217238106Sdes */
218238106Sdesstruct port_comm {
219238106Sdes	/** next in free list */
220238106Sdes	struct port_comm* next;
221238106Sdes	/** which port number (when in use) */
222238106Sdes	int number;
223238106Sdes	/** interface it is used in */
224238106Sdes	struct port_if* pif;
225238106Sdes	/** index in the out array of the interface */
226238106Sdes	int index;
227238106Sdes	/** number of outstanding queries on this port */
228238106Sdes	int num_outstanding;
229238106Sdes	/** UDP commpoint, fd=-1 if not in use */
230238106Sdes	struct comm_point* cp;
231238106Sdes};
232238106Sdes
233238106Sdes/**
234368693Scy * Reuse TCP connection, still open can be used again.
235368693Scy */
236368693Scystruct reuse_tcp {
237368693Scy	/** rbtree node with links in tcp_reuse tree. key is NULL when not
238368693Scy	 * in tree. Both active and empty connections are in the tree.
239368693Scy	 * key is a pointer to this structure, the members used to compare
240368693Scy	 * are the sockaddr and and then is-ssl bool, and then ptr value is
241368693Scy	 * used in case the same address exists several times in the tree
242368693Scy	 * when there are multiple connections to the same destination to
243368693Scy	 * make the rbtree items unique. */
244368693Scy	rbnode_type node;
245368693Scy	/** the key for the tcp_reuse tree. address of peer, ip4 or ip6,
246368693Scy	 * and port number of peer */
247368693Scy	struct sockaddr_storage addr;
248368693Scy	/** length of addr */
249368693Scy	socklen_t addrlen;
250368693Scy	/** also key for tcp_reuse tree, if ssl is used */
251368693Scy	int is_ssl;
252368693Scy	/** lru chain, so that the oldest can be removed to get a new
253368693Scy	 * connection when all are in (re)use. oldest is last in list.
254368693Scy	 * The lru only contains empty connections waiting for reuse,
255368693Scy	 * the ones with active queries are not on the list because they
256368693Scy	 * do not need to be closed to make space for others.  They already
257368693Scy	 * service a query so the close for another query does not help
258368693Scy	 * service a larger number of queries. */
259368693Scy	struct reuse_tcp* lru_next, *lru_prev;
260368693Scy	/** true if the reuse_tcp item is on the lru list with empty items */
261368693Scy	int item_on_lru_list;
262368693Scy	/** the connection to reuse, the fd is non-1 and is open.
263368693Scy	 * the addr and port determine where the connection is going,
264368693Scy	 * and is key to the rbtree.  The SSL ptr determines if it is
265368693Scy	 * a TLS connection or a plain TCP connection there.  And TLS
266368693Scy	 * or not is also part of the key to the rbtree.
267368693Scy	 * There is a timeout and read event on the fd, to close it. */
268368693Scy	struct pending_tcp* pending;
269368693Scy	/**
270368693Scy	 * The more read again value pointed to by the commpoint
271368693Scy	 * tcp_more_read_again pointer, so that it exists after commpoint
272368693Scy	 * delete
273368693Scy	 */
274368693Scy	int cp_more_read_again;
275368693Scy	/**
276368693Scy	 * The more write again value pointed to by the commpoint
277368693Scy	 * tcp_more_write_again pointer, so that it exists after commpoint
278368693Scy	 * delete
279368693Scy	 */
280368693Scy	int cp_more_write_again;
281368693Scy	/** rbtree with other queries waiting on the connection, by ID number,
282368693Scy	 * of type struct waiting_tcp. It is for looking up received
283368693Scy	 * answers to the structure for callback.  And also to see if ID
284368693Scy	 * numbers are unused and can be used for a new query.
285368693Scy	 * The write_wait elements are also in the tree, so that ID numbers
286368693Scy	 * can be looked up also for them.  They are bool write_wait_queued. */
287368693Scy	rbtree_type tree_by_id;
288368693Scy	/** list of queries waiting to be written on the channel,
289368693Scy	 * if NULL no queries are waiting to be written and the pending->query
290368693Scy	 * is the query currently serviced.  The first is the next in line.
291368693Scy	 * They are also in the tree_by_id. Once written, the are removed
292368693Scy	 * from this list, but stay in the tree. */
293368693Scy	struct waiting_tcp* write_wait_first, *write_wait_last;
294368693Scy	/** the outside network it is part of */
295368693Scy	struct outside_network* outnet;
296368693Scy};
297368693Scy
298368693Scy/** max number of queries on a reuse connection */
299368693Scy#define MAX_REUSE_TCP_QUERIES 200
300368693Scy/** timeout for REUSE entries in milliseconds. */
301368693Scy#define REUSE_TIMEOUT 60000
302368693Scy
303368693Scy/**
304238106Sdes * A query that has an answer pending for it.
305238106Sdes */
306238106Sdesstruct pending {
307238106Sdes	/** redblacktree entry, key is the pending struct(id, addr). */
308356345Scy	rbnode_type node;
309238106Sdes	/** the ID for the query. int so that a value out of range can
310238106Sdes	 * be used to signify a pending that is for certain not present in
311238106Sdes	 * the rbtree. (and for which deletion is safe). */
312238106Sdes	unsigned int id;
313238106Sdes	/** remote address. */
314238106Sdes	struct sockaddr_storage addr;
315238106Sdes	/** length of addr field in use. */
316238106Sdes	socklen_t addrlen;
317238106Sdes	/** comm point it was sent on (and reply must come back on). */
318238106Sdes	struct port_comm* pc;
319238106Sdes	/** timeout event */
320238106Sdes	struct comm_timer* timer;
321238106Sdes	/** callback for the timeout, error or reply to the message */
322356345Scy	comm_point_callback_type* cb;
323238106Sdes	/** callback user argument */
324238106Sdes	void* cb_arg;
325238106Sdes	/** the outside network it is part of */
326238106Sdes	struct outside_network* outnet;
327276605Sdes	/** the corresponding serviced_query */
328276605Sdes	struct serviced_query* sq;
329238106Sdes
330238106Sdes	/*---- filled if udp pending is waiting -----*/
331238106Sdes	/** next in waiting list. */
332238106Sdes	struct pending* next_waiting;
333238106Sdes	/** timeout in msec */
334238106Sdes	int timeout;
335238106Sdes	/** The query itself, the query packet to send. */
336238106Sdes	uint8_t* pkt;
337238106Sdes	/** length of query packet. */
338238106Sdes	size_t pkt_len;
339238106Sdes};
340238106Sdes
341238106Sdes/**
342238106Sdes * Pending TCP query to server.
343238106Sdes */
344238106Sdesstruct pending_tcp {
345238106Sdes	/** next in list of free tcp comm points, or NULL. */
346238106Sdes	struct pending_tcp* next_free;
347238106Sdes	/** tcp comm point it was sent on (and reply must come back on). */
348238106Sdes	struct comm_point* c;
349238106Sdes	/** the query being serviced, NULL if the pending_tcp is unused. */
350238106Sdes	struct waiting_tcp* query;
351368693Scy	/** the pre-allocated reuse tcp structure.  if ->pending is nonNULL
352368693Scy	 * it is in use and the connection is waiting for reuse.
353368693Scy	 * It is here for memory pre-allocation, and used to make this
354368693Scy	 * pending_tcp wait for reuse. */
355368693Scy	struct reuse_tcp reuse;
356238106Sdes};
357238106Sdes
358238106Sdes/**
359238106Sdes * Query waiting for TCP buffer.
360238106Sdes */
361238106Sdesstruct waiting_tcp {
362238106Sdes	/**
363238106Sdes	 * next in waiting list.
364368693Scy	 * if on_tcp_waiting_list==0, this points to the pending_tcp structure.
365238106Sdes	 */
366238106Sdes	struct waiting_tcp* next_waiting;
367368693Scy	/** if true the item is on the tcp waiting list and next_waiting
368368693Scy	 * is used for that.  If false, the next_waiting points to the
369368693Scy	 * pending_tcp */
370368693Scy	int on_tcp_waiting_list;
371368693Scy	/** next and prev in query waiting list for stream connection */
372368693Scy	struct waiting_tcp* write_wait_prev, *write_wait_next;
373368693Scy	/** true if the waiting_tcp structure is on the write_wait queue */
374368693Scy	int write_wait_queued;
375368693Scy	/** entry in reuse.tree_by_id, if key is NULL, not in tree, otherwise,
376368693Scy	 * this struct is key and sorted by ID (from waiting_tcp.id). */
377368693Scy	rbnode_type id_node;
378368693Scy	/** the ID for the query; checked in reply */
379368693Scy	uint16_t id;
380238106Sdes	/** timeout event; timer keeps running whether the query is
381238106Sdes	 * waiting for a buffer or the tcp reply is pending */
382238106Sdes	struct comm_timer* timer;
383368693Scy	/** timeout in msec */
384368693Scy	int timeout;
385238106Sdes	/** the outside network it is part of */
386238106Sdes	struct outside_network* outnet;
387238106Sdes	/** remote address. */
388238106Sdes	struct sockaddr_storage addr;
389238106Sdes	/** length of addr field in use. */
390238106Sdes	socklen_t addrlen;
391238106Sdes	/**
392238106Sdes	 * The query itself, the query packet to send.
393238106Sdes	 * allocated after the waiting_tcp structure.
394238106Sdes	 */
395238106Sdes	uint8_t* pkt;
396238106Sdes	/** length of query packet. */
397238106Sdes	size_t pkt_len;
398368693Scy	/** callback for the timeout, error or reply to the message,
399368693Scy	 * or NULL if no user is waiting. the entry uses an ID number.
400368693Scy	 * a query that was written is no longer needed, but the ID number
401368693Scy	 * and a reply will come back and can be ignored if NULL */
402356345Scy	comm_point_callback_type* cb;
403238106Sdes	/** callback user argument */
404238106Sdes	void* cb_arg;
405238106Sdes	/** if it uses ssl upstream */
406238106Sdes	int ssl_upstream;
407356345Scy	/** ref to the tls_auth_name from the serviced_query */
408356345Scy	char* tls_auth_name;
409368693Scy	/** the packet was involved in an error, to stop looping errors */
410368693Scy	int error_count;
411238106Sdes};
412238106Sdes
413238106Sdes/**
414238106Sdes * Callback to party interested in serviced query results.
415238106Sdes */
416238106Sdesstruct service_callback {
417238106Sdes	/** next in callback list */
418238106Sdes	struct service_callback* next;
419238106Sdes	/** callback function */
420356345Scy	comm_point_callback_type* cb;
421238106Sdes	/** user argument for callback function */
422238106Sdes	void* cb_arg;
423238106Sdes};
424238106Sdes
425238106Sdes/** fallback size for fragmentation for EDNS in IPv4 */
426249141Sdes#define EDNS_FRAG_SIZE_IP4 1472
427238106Sdes/** fallback size for EDNS in IPv6, fits one fragment with ip6-tunnel-ids */
428249141Sdes#define EDNS_FRAG_SIZE_IP6 1232
429238106Sdes
430238106Sdes/**
431238106Sdes * Query service record.
432238106Sdes * Contains query and destination. UDP, TCP, EDNS are all tried.
433238106Sdes * complete with retries and timeouts. A number of interested parties can
434238106Sdes * receive a callback.
435238106Sdes */
436238106Sdesstruct serviced_query {
437238106Sdes	/** The rbtree node, key is this record */
438356345Scy	rbnode_type node;
439238106Sdes	/** The query that needs to be answered. Starts with flags u16,
440238106Sdes	 * then qdcount, ..., including qname, qtype, qclass. Does not include
441238106Sdes	 * EDNS record. */
442238106Sdes	uint8_t* qbuf;
443238106Sdes	/** length of qbuf. */
444238106Sdes	size_t qbuflen;
445238106Sdes	/** If an EDNS section is included, the DO/CD bit will be turned on. */
446238106Sdes	int dnssec;
447238106Sdes	/** We want signatures, or else the answer is likely useless */
448238106Sdes	int want_dnssec;
449276605Sdes	/** ignore capsforid */
450276605Sdes	int nocaps;
451238106Sdes	/** tcp upstream used, use tcp, or ssl_upstream for SSL */
452238106Sdes	int tcp_upstream, ssl_upstream;
453356345Scy	/** the name of the tls authentication name, eg. 'ns.example.com'
454356345Scy	 * or NULL */
455356345Scy	char* tls_auth_name;
456238106Sdes	/** where to send it */
457238106Sdes	struct sockaddr_storage addr;
458238106Sdes	/** length of addr field in use. */
459238106Sdes	socklen_t addrlen;
460238106Sdes	/** zone name, uncompressed domain name in wireformat */
461238106Sdes	uint8_t* zone;
462238106Sdes	/** length of zone name */
463238106Sdes	size_t zonelen;
464238106Sdes	/** qtype */
465238106Sdes	int qtype;
466238106Sdes	/** current status */
467238106Sdes	enum serviced_query_status {
468238106Sdes		/** initial status */
469238106Sdes		serviced_initial,
470238106Sdes		/** UDP with EDNS sent */
471238106Sdes		serviced_query_UDP_EDNS,
472238106Sdes		/** UDP without EDNS sent */
473238106Sdes		serviced_query_UDP,
474238106Sdes		/** TCP with EDNS sent */
475238106Sdes		serviced_query_TCP_EDNS,
476238106Sdes		/** TCP without EDNS sent */
477238106Sdes		serviced_query_TCP,
478238106Sdes		/** probe to test noEDNS0 (EDNS gives FORMERRorNOTIMP) */
479238106Sdes		serviced_query_UDP_EDNS_fallback,
480238106Sdes		/** probe to test TCP noEDNS0 (EDNS gives FORMERRorNOTIMP) */
481238106Sdes		serviced_query_TCP_EDNS_fallback,
482238106Sdes		/** send UDP query with EDNS1480 (or 1280) */
483238106Sdes		serviced_query_UDP_EDNS_FRAG
484238106Sdes	}
485238106Sdes		/** variable with current status */
486238106Sdes		status;
487238106Sdes	/** true if serviced_query is scheduled for deletion already */
488238106Sdes	int to_be_deleted;
489238106Sdes	/** number of UDP retries */
490238106Sdes	int retry;
491238106Sdes	/** time last UDP was sent */
492238106Sdes	struct timeval last_sent_time;
493356345Scy	/** rtt of last message */
494238106Sdes	int last_rtt;
495238106Sdes	/** do we know edns probe status already, for UDP_EDNS queries */
496238106Sdes	int edns_lame_known;
497307729Sdes	/** edns options to use for sending upstream packet */
498307729Sdes	struct edns_option* opt_list;
499238106Sdes	/** outside network this is part of */
500238106Sdes	struct outside_network* outnet;
501238106Sdes	/** list of interested parties that need callback on results. */
502238106Sdes	struct service_callback* cblist;
503238106Sdes	/** the UDP or TCP query that is pending, see status which */
504238106Sdes	void* pending;
505369939Sgit2svn	/** block size with which to pad encrypted queries (default: 128) */
506369939Sgit2svn	size_t padding_block_size;
507238106Sdes};
508238106Sdes
509238106Sdes/**
510238106Sdes * Create outside_network structure with N udp ports.
511238106Sdes * @param base: the communication base to use for event handling.
512238106Sdes * @param bufsize: size for network buffers.
513238106Sdes * @param num_ports: number of udp ports to open per interface.
514238106Sdes * @param ifs: interface names (or NULL for default interface).
515238106Sdes *    These interfaces must be able to access all authoritative servers.
516238106Sdes * @param num_ifs: number of names in array ifs.
517238106Sdes * @param do_ip4: service IP4.
518238106Sdes * @param do_ip6: service IP6.
519238106Sdes * @param num_tcp: number of outgoing tcp buffers to preallocate.
520366095Scy * @param dscp: DSCP to use.
521238106Sdes * @param infra: pointer to infra cached used for serviced queries.
522238106Sdes * @param rnd: stored to create random numbers for serviced queries.
523238106Sdes * @param use_caps_for_id: enable to use 0x20 bits to encode id randomness.
524238106Sdes * @param availports: array of available ports.
525238106Sdes * @param numavailports: number of available ports in array.
526238106Sdes * @param unwanted_threshold: when to take defensive action.
527238106Sdes * @param unwanted_action: the action to take.
528238106Sdes * @param unwanted_param: user parameter to action.
529296415Sdes * @param tcp_mss: maximum segment size of tcp socket.
530238106Sdes * @param do_udp: if udp is done.
531238106Sdes * @param sslctx: context to create outgoing connections with (if enabled).
532266114Sdes * @param delayclose: if not 0, udp sockets are delayed before timeout closure.
533266114Sdes * 	msec to wait on timeouted udp sockets.
534366095Scy * @param tls_use_sni: if SNI is used for TLS connections.
535276605Sdes * @param dtenv: environment to send dnstap events with (if enabled).
536368693Scy * @param udp_connect: if the udp_connect option is enabled.
537238106Sdes * @return: the new structure (with no pending answers) or NULL on error.
538238106Sdes */
539238106Sdesstruct outside_network* outside_network_create(struct comm_base* base,
540238106Sdes	size_t bufsize, size_t num_ports, char** ifs, int num_ifs,
541366095Scy	int do_ip4, int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra,
542238106Sdes	struct ub_randstate* rnd, int use_caps_for_id, int* availports,
543296415Sdes	int numavailports, size_t unwanted_threshold, int tcp_mss,
544238106Sdes	void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
545368693Scy	void* sslctx, int delayclose, int tls_use_sni, struct dt_env *dtenv,
546368693Scy	int udp_connect);
547238106Sdes
548238106Sdes/**
549238106Sdes * Delete outside_network structure.
550238106Sdes * @param outnet: object to delete.
551238106Sdes */
552238106Sdesvoid outside_network_delete(struct outside_network* outnet);
553238106Sdes
554238106Sdes/**
555238106Sdes * Prepare for quit. Sends no more queries, even if queued up.
556238106Sdes * @param outnet: object to prepare for removal
557238106Sdes */
558238106Sdesvoid outside_network_quit_prepare(struct outside_network* outnet);
559238106Sdes
560238106Sdes/**
561238106Sdes * Send UDP query, create pending answer.
562238106Sdes * Changes the ID for the query to be random and unique for that destination.
563276605Sdes * @param sq: serviced query.
564238106Sdes * @param packet: wireformat query to send to destination.
565238106Sdes * @param timeout: in milliseconds from now.
566238106Sdes * @param callback: function to call on error, timeout or reply.
567238106Sdes * @param callback_arg: user argument for callback function.
568238106Sdes * @return: NULL on error for malloc or socket. Else the pending query object.
569238106Sdes */
570276605Sdesstruct pending* pending_udp_query(struct serviced_query* sq,
571356345Scy	struct sldns_buffer* packet, int timeout, comm_point_callback_type* callback,
572238106Sdes	void* callback_arg);
573238106Sdes
574238106Sdes/**
575238106Sdes * Send TCP query. May wait for TCP buffer. Selects ID to be random, and
576238106Sdes * checks id.
577276605Sdes * @param sq: serviced query.
578238106Sdes * @param packet: wireformat query to send to destination. copied from.
579356345Scy * @param timeout: in milliseconds from now.
580238106Sdes *    Timer starts running now. Timer may expire if all buffers are used,
581238106Sdes *    without any query been sent to the server yet.
582238106Sdes * @param callback: function to call on error, timeout or reply.
583238106Sdes * @param callback_arg: user argument for callback function.
584238106Sdes * @return: false on error for malloc or socket. Else the pending TCP object.
585238106Sdes */
586276605Sdesstruct waiting_tcp* pending_tcp_query(struct serviced_query* sq,
587356345Scy	struct sldns_buffer* packet, int timeout, comm_point_callback_type* callback,
588276605Sdes	void* callback_arg);
589238106Sdes
590238106Sdes/**
591238106Sdes * Delete pending answer.
592238106Sdes * @param outnet: outside network the pending query is part of.
593238106Sdes *    Internal feature: if outnet is NULL, p is not unlinked from rbtree.
594238106Sdes * @param p: deleted
595238106Sdes */
596238106Sdesvoid pending_delete(struct outside_network* outnet, struct pending* p);
597238106Sdes
598238106Sdes/**
599238106Sdes * Perform a serviced query to the authoritative servers.
600238106Sdes * Duplicate efforts are detected, and EDNS, TCP and UDP retry is performed.
601238106Sdes * @param outnet: outside network, with rbtree of serviced queries.
602356345Scy * @param qinfo: query info.
603238106Sdes * @param flags: flags u16 (host format), includes opcode, CD bit.
604238106Sdes * @param dnssec: if set, DO bit is set in EDNS queries.
605238106Sdes *	If the value includes BIT_CD, CD bit is set when in EDNS queries.
606238106Sdes *	If the value includes BIT_DO, DO bit is set when in EDNS queries.
607238106Sdes * @param want_dnssec: signatures are needed, without EDNS the answer is
608238106Sdes * 	likely to be useless.
609276605Sdes * @param nocaps: ignore use_caps_for_id and use unperturbed qname.
610238106Sdes * @param tcp_upstream: use TCP for upstream queries.
611238106Sdes * @param ssl_upstream: use SSL for upstream queries.
612356345Scy * @param tls_auth_name: when ssl_upstream is true, use this name to check
613356345Scy * 	the server's peer certificate.
614238106Sdes * @param addr: to which server to send the query.
615238106Sdes * @param addrlen: length of addr.
616238106Sdes * @param zone: name of the zone of the delegation point. wireformat dname.
617238106Sdes	This is the delegation point name for which the server is deemed
618238106Sdes	authoritative.
619238106Sdes * @param zonelen: length of zone.
620356345Scy * @param qstate: module qstate. Mainly for inspecting the available
621356345Scy *	edns_opts_lists.
622356345Scy * @param callback: callback function.
623356345Scy * @param callback_arg: user argument to callback function.
624238106Sdes * @param buff: scratch buffer to create query contents in. Empty on exit.
625356345Scy * @param env: the module environment.
626238106Sdes * @return 0 on error, or pointer to serviced query that is used to answer
627238106Sdes *	this serviced query may be shared with other callbacks as well.
628238106Sdes */
629238106Sdesstruct serviced_query* outnet_serviced_query(struct outside_network* outnet,
630356345Scy	struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
631356345Scy	int nocaps, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
632307729Sdes	struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
633356345Scy	size_t zonelen, struct module_qstate* qstate,
634356345Scy	comm_point_callback_type* callback, void* callback_arg,
635356345Scy	struct sldns_buffer* buff, struct module_env* env);
636238106Sdes
637238106Sdes/**
638238106Sdes * Remove service query callback.
639238106Sdes * If that leads to zero callbacks, the query is completely cancelled.
640238106Sdes * @param sq: serviced query to adjust.
641238106Sdes * @param cb_arg: callback argument of callback that needs removal.
642238106Sdes *	same as the callback_arg to outnet_serviced_query().
643238106Sdes */
644238106Sdesvoid outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg);
645238106Sdes
646238106Sdes/**
647238106Sdes * Get memory size in use by outside network.
648238106Sdes * Counts buffers and outstanding query (serviced queries) malloced data.
649238106Sdes * @param outnet: outside network structure.
650238106Sdes * @return size in bytes.
651238106Sdes */
652238106Sdessize_t outnet_get_mem(struct outside_network* outnet);
653238106Sdes
654238106Sdes/**
655238106Sdes * Get memory size in use by serviced query while it is servicing callbacks.
656238106Sdes * This takes into account the pre-deleted status of it; it will be deleted
657238106Sdes * when the callbacks are done.
658238106Sdes * @param sq: serviced query.
659238106Sdes * @return size in bytes.
660238106Sdes */
661238106Sdessize_t serviced_get_mem(struct serviced_query* sq);
662238106Sdes
663368693Scy/** Pick random ID value for a tcp stream, avoids existing IDs. */
664368693Scyuint16_t reuse_tcp_select_id(struct reuse_tcp* reuse,
665368693Scy	struct outside_network* outnet);
666368693Scy
667368693Scy/** find element in tree by id */
668368693Scystruct waiting_tcp* reuse_tcp_by_id_find(struct reuse_tcp* reuse, uint16_t id);
669368693Scy
670368693Scy/** insert element in tree by id */
671368693Scyvoid reuse_tree_by_id_insert(struct reuse_tcp* reuse, struct waiting_tcp* w);
672368693Scy
673368693Scy/** delete readwait waiting_tcp elements, deletes the elements in the list */
674368693Scyvoid reuse_del_readwait(rbtree_type* tree_by_id);
675368693Scy
676356345Scy/** get TCP file descriptor for address, returns -1 on failure,
677356345Scy * tcp_mss is 0 or maxseg size to set for TCP packets. */
678366095Scyint outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int dscp);
679356345Scy
680356345Scy/**
681356345Scy * Create udp commpoint suitable for sending packets to the destination.
682356345Scy * @param outnet: outside_network with the comm_base it is attached to,
683356345Scy * 	with the outgoing interfaces chosen from, and rnd gen for random.
684356345Scy * @param cb: callback function for the commpoint.
685356345Scy * @param cb_arg: callback argument for cb.
686356345Scy * @param to_addr: intended destination.
687356345Scy * @param to_addrlen: length of to_addr.
688356345Scy * @return commpoint that you can comm_point_send_udp_msg with, or NULL.
689356345Scy */
690356345Scystruct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet,
691356345Scy	comm_point_callback_type* cb, void* cb_arg,
692356345Scy	struct sockaddr_storage* to_addr, socklen_t to_addrlen);
693356345Scy
694356345Scy/**
695356345Scy * Create tcp commpoint suitable for communication to the destination.
696356345Scy * It also performs connect() to the to_addr.
697356345Scy * @param outnet: outside_network with the comm_base it is attached to,
698356345Scy * 	and the tcp_mss.
699356345Scy * @param cb: callback function for the commpoint.
700356345Scy * @param cb_arg: callback argument for cb.
701356345Scy * @param to_addr: intended destination.
702356345Scy * @param to_addrlen: length of to_addr.
703356345Scy * @param query: initial packet to send writing, in buffer.  It is copied
704356345Scy * 	to the commpoint buffer that is created.
705356345Scy * @param timeout: timeout for the TCP connection.
706356345Scy * 	timeout in milliseconds, or -1 for no (change to the) timeout.
707356345Scy *	So seconds*1000.
708356345Scy * @param ssl: set to true for TLS.
709356345Scy * @param host: hostname for host name verification of TLS (or NULL if no TLS).
710356345Scy * @return tcp_out commpoint, or NULL.
711356345Scy */
712356345Scystruct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
713356345Scy	comm_point_callback_type* cb, void* cb_arg,
714356345Scy	struct sockaddr_storage* to_addr, socklen_t to_addrlen,
715356345Scy	struct sldns_buffer* query, int timeout, int ssl, char* host);
716356345Scy
717356345Scy/**
718356345Scy * Create http commpoint suitable for communication to the destination.
719356345Scy * Creates the http request buffer. It also performs connect() to the to_addr.
720356345Scy * @param outnet: outside_network with the comm_base it is attached to,
721356345Scy * 	and the tcp_mss.
722356345Scy * @param cb: callback function for the commpoint.
723356345Scy * @param cb_arg: callback argument for cb.
724356345Scy * @param to_addr: intended destination.
725356345Scy * @param to_addrlen: length of to_addr.
726356345Scy * @param timeout: timeout for the TCP connection.
727356345Scy * 	timeout in milliseconds, or -1 for no (change to the) timeout.
728356345Scy *	So seconds*1000.
729356345Scy * @param ssl: set to true for https.
730356345Scy * @param host: hostname to use for the destination. part of http request.
731356345Scy * @param path: pathname to lookup, eg. name of the file on the destination.
732356345Scy * @return http_out commpoint, or NULL.
733356345Scy */
734356345Scystruct comm_point* outnet_comm_point_for_http(struct outside_network* outnet,
735356345Scy	comm_point_callback_type* cb, void* cb_arg,
736356345Scy	struct sockaddr_storage* to_addr, socklen_t to_addrlen, int timeout,
737356345Scy	int ssl, char* host, char* path);
738356345Scy
739356345Scy/** connect tcp connection to addr, 0 on failure */
740356345Scyint outnet_tcp_connect(int s, struct sockaddr_storage* addr, socklen_t addrlen);
741356345Scy
742238106Sdes/** callback for incoming udp answers from the network */
743238106Sdesint outnet_udp_cb(struct comm_point* c, void* arg, int error,
744238106Sdes	struct comm_reply *reply_info);
745238106Sdes
746238106Sdes/** callback for pending tcp connections */
747238106Sdesint outnet_tcp_cb(struct comm_point* c, void* arg, int error,
748238106Sdes	struct comm_reply *reply_info);
749238106Sdes
750238106Sdes/** callback for udp timeout */
751238106Sdesvoid pending_udp_timer_cb(void *arg);
752238106Sdes
753266114Sdes/** callback for udp delay for timeout */
754266114Sdesvoid pending_udp_timer_delay_cb(void *arg);
755266114Sdes
756238106Sdes/** callback for outgoing TCP timer event */
757238106Sdesvoid outnet_tcptimer(void* arg);
758238106Sdes
759238106Sdes/** callback for serviced query UDP answers */
760238106Sdesint serviced_udp_callback(struct comm_point* c, void* arg, int error,
761238106Sdes        struct comm_reply* rep);
762238106Sdes
763238106Sdes/** TCP reply or error callback for serviced queries */
764238106Sdesint serviced_tcp_callback(struct comm_point* c, void* arg, int error,
765238106Sdes        struct comm_reply* rep);
766238106Sdes
767238106Sdes/** compare function of pending rbtree */
768238106Sdesint pending_cmp(const void* key1, const void* key2);
769238106Sdes
770238106Sdes/** compare function of serviced query rbtree */
771238106Sdesint serviced_cmp(const void* key1, const void* key2);
772238106Sdes
773368693Scy/** compare function of reuse_tcp rbtree in outside_network struct */
774368693Scyint reuse_cmp(const void* key1, const void* key2);
775368693Scy
776368693Scy/** compare function of reuse_tcp tree_by_id rbtree */
777368693Scyint reuse_id_cmp(const void* key1, const void* key2);
778368693Scy
779238106Sdes#endif /* OUTSIDE_NETWORK_H */
780