xref: /openbsd/usr.sbin/nsd/xfrd-tcp.h (revision d89ec533)
1 /*
2  * xfrd-tcp.h - XFR (transfer) Daemon TCP system header file. Manages tcp conn.
3  *
4  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 
10 #ifndef XFRD_TCP_H
11 #define XFRD_TCP_H
12 
13 #include "xfrd.h"
14 #ifdef HAVE_TLS_1_3
15 #include <openssl/ssl.h>
16 #endif
17 
18 
19 struct buffer;
20 struct xfrd_zone;
21 struct xfrd_soa;
22 struct xfrd_state;
23 struct region;
24 struct dname;
25 struct acl_options;
26 
27 struct xfrd_tcp_pipeline;
28 typedef struct xfrd_tcp xfrd_tcp_type;
29 typedef struct xfrd_tcp_set xfrd_tcp_set_type;
30 /*
31  * A set of xfrd tcp connections.
32  */
33 struct xfrd_tcp_set {
34 	/* tcp connections, each has packet and read/wr state */
35 	struct xfrd_tcp_pipeline *tcp_state[XFRD_MAX_TCP];
36 	/* number of TCP connections in use. */
37 	int tcp_count;
38 	/* TCP timeout. */
39 	int tcp_timeout;
40 	/* rbtree with pipelines sorted by master */
41 	rbtree_type* pipetree;
42 #ifdef HAVE_TLS_1_3
43 	/* XoT: SSL context */
44 	SSL_CTX* ssl_ctx;
45 #endif
46 	/* double linked list of zones waiting for a TCP connection */
47 	struct xfrd_zone *tcp_waiting_first, *tcp_waiting_last;
48 };
49 
50 /*
51  * Structure to keep track of an open tcp connection
52  * The xfrd tcp connection is used to first make a request
53  * Then to receive the answer packet(s).
54  */
55 struct xfrd_tcp {
56 	/* tcp connection state */
57 	/* state: reading or writing */
58 	uint8_t is_reading;
59 
60 	/* how many bytes have been read/written - total,
61 	   incl. tcp length bytes */
62 	uint32_t total_bytes;
63 
64 	/* msg len bytes */
65 	uint16_t msglen;
66 
67 	/* fd of connection. -1 means unconnected */
68 	int fd;
69 
70 	/* packet buffer of connection */
71 	struct buffer* packet;
72 };
73 
74 /* use illegal pointer value to denote skipped ID number.
75  * if this does not work, we can allocate with malloc */
76 #define TCP_NULL_SKIP ((struct xfrd_zone*)-1)
77 /* the number of ID values (16 bits) for a pipeline */
78 #define ID_PIPE_NUM 65536
79 
80 /**
81  * The tcp pipeline key structure. By ip_len, ip, num_unused and unique by
82  * pointer value.
83  */
84 struct xfrd_tcp_pipeline_key {
85 	/* the rbtree node, sorted by IP and nr of unused queries */
86 	rbnode_type node;
87 	/* destination IP address */
88 #ifdef INET6
89 	struct sockaddr_storage ip;
90 #else
91 	struct sockaddr_in ip;
92 #endif /* INET6 */
93 	socklen_t ip_len;
94 	/* number of unused IDs.  used IDs are waiting to send their query,
95 	 * or have been sent but not not all answer packets have been received.
96 	 * Sorted by num_unused, so a lookup smaller-equal for 65536 finds the
97 	 * connection to that master that has the most free IDs. */
98 	int num_unused;
99 	/* number of skip-set IDs (these are 'in-use') */
100 	int num_skip;
101 };
102 
103 /**
104  * Structure to keep track of a pipelined set of queries on
105  * an open tcp connection.  The queries may be answered with
106  * interleaved answer packets, the ID number disambiguates.
107  * Sorted by the master IP address so you can use lookup with
108  * smaller-or-equal to find the tcp connection most suitable.
109  */
110 struct xfrd_tcp_pipeline {
111 	/* the key information for the tcp pipeline, in its own
112 	 * struct so it can be referenced on its own for comparison funcs */
113 	struct xfrd_tcp_pipeline_key key;
114 
115 	int handler_added;
116 	/* the event handler for this pipe (it'll disambiguate by ID) */
117 	struct event handler;
118 
119 	/* the tcp connection to use for reading */
120 	struct xfrd_tcp* tcp_r;
121 	/* the tcp connection to use for writing, if it is done successfully,
122 	 * then the first zone from the sendlist can be removed. */
123 	struct xfrd_tcp* tcp_w;
124 	/* once a byte has been written, handshake complete */
125 	int connection_established;
126 #ifdef HAVE_TLS_1_3
127 	/* XoT: SSL object */
128 	SSL *ssl;
129 	/* XoT: if SSL handshake is not done, handshake_want indicates the
130 	 * last error. This may be SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE
131 	 * when the handshake is still in progress.
132 	 */
133 	int  handshake_want;
134 	/* XoT: 1 if the SSL handshake has succeeded, 0 otherwise */
135 	int  handshake_done;
136 #endif
137 
138 	/* list of queries that want to send, first to get write event,
139 	 * if NULL, no write event interest */
140 	struct xfrd_zone* tcp_send_first, *tcp_send_last;
141 	/* the unused and id arrays must be last in the structure */
142 	/* per-ID number the queries that have this ID number, every
143 	 * query owns one ID numbers (until it is done). NULL: unused
144 	 * When a query is done but not all answer-packets have been
145 	 * consumed for that ID number, the rest is skipped, this
146 	 * is denoted with the pointer-value TCP_NULL_SKIP, the ids that
147 	 * are skipped are not on the unused list.  They may be
148 	 * removed once the last answer packet is skipped.
149 	 * ID_PIPE_NUM-num_unused values in the id array are nonNULL (either
150 	 * a zone pointer or SKIP) */
151 	struct xfrd_zone* id[ID_PIPE_NUM];
152 	/* unused ID numbers; the first part of the array contains the IDs */
153 	uint16_t unused[ID_PIPE_NUM];
154 };
155 
156 /* create set of tcp connections */
157 struct xfrd_tcp_set* xfrd_tcp_set_create(struct region* region, const char *tls_cert_bundle);
158 
159 /* init tcp state */
160 struct xfrd_tcp* xfrd_tcp_create(struct region* region, size_t bufsize);
161 /* obtain tcp connection for a zone (or wait) */
162 void xfrd_tcp_obtain(struct xfrd_tcp_set* set, struct xfrd_zone* zone);
163 /* release tcp connection for a zone (starts waiting) */
164 void xfrd_tcp_release(struct xfrd_tcp_set* set, struct xfrd_zone* zone);
165 /* release tcp pipe entirely (does not stop the zones inside it) */
166 void xfrd_tcp_pipe_release(struct xfrd_tcp_set* set,
167 	struct xfrd_tcp_pipeline* tp, int conn);
168 /* use tcp connection to start xfr */
169 void xfrd_tcp_setup_write_packet(struct xfrd_tcp_pipeline* tp,
170 	struct xfrd_zone* zone);
171 /* initialize tcp_state for a zone. Opens the connection. true on success.*/
172 int xfrd_tcp_open(struct xfrd_tcp_set* set, struct xfrd_tcp_pipeline* tp,
173 	struct xfrd_zone* zone);
174 /* read data from tcp, maybe partial read */
175 void xfrd_tcp_read(struct xfrd_tcp_pipeline* tp);
176 /* write data to tcp, maybe a partial write */
177 void xfrd_tcp_write(struct xfrd_tcp_pipeline* tp, struct xfrd_zone* zone);
178 /* handle tcp pipe events */
179 void xfrd_handle_tcp_pipe(int fd, short event, void* arg);
180 
181 /*
182  * Read from a stream connection (size16)+packet into buffer.
183  * returns value is
184  *	-1 on error.
185  *	0 on short read, call back later.
186  *	1 on completed read.
187  * On first call, make sure total_bytes = 0, msglen=0, buffer_clear().
188  * and the packet and fd need to be set.
189  */
190 int conn_read(struct xfrd_tcp* conn);
191 /*
192  * Write to a stream connection (size16)+packet.
193  * return value is
194  * -1 on error. 0 on short write, call back later. 1 completed write.
195  * On first call, make sure total_bytes=0, msglen=buffer_limit(),
196  * buffer_flipped(). packet and fd need to be set.
197  */
198 int conn_write(struct xfrd_tcp* conn);
199 
200 /* setup DNS packet for a query of this type */
201 void xfrd_setup_packet(struct buffer* packet,
202         uint16_t type, uint16_t klass, const struct dname* dname, uint16_t qid);
203 /* write soa in network format to the packet buffer */
204 void xfrd_write_soa_buffer(struct buffer* packet,
205         const struct dname* apex, struct xfrd_soa* soa);
206 /* use acl address to setup sockaddr struct, returns length of addr. */
207 socklen_t xfrd_acl_sockaddr_to(struct acl_options* acl,
208 #ifdef INET6
209 	struct sockaddr_storage *to);
210 #else
211 	struct sockaddr_in *to);
212 #endif /* INET6 */
213 
214 socklen_t xfrd_acl_sockaddr_frm(struct acl_options* acl,
215 #ifdef INET6
216 	struct sockaddr_storage *frm);
217 #else
218 	struct sockaddr_in *frm);
219 #endif /* INET6 */
220 
221 /* create pipeline tcp structure */
222 struct xfrd_tcp_pipeline* xfrd_tcp_pipeline_create(region_type* region);
223 
224 #endif /* XFRD_TCP_H */
225