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