djbdnscurve6 45
djbdnscurve6
Loading...
Searching...
No Matches
dnscache.c
Go to the documentation of this file.
1#include <unistd.h>
2#include "case.h"
3#include "env.h"
4#include "exit.h"
5#include "scan.h"
6#include "logmsg.h"
7#include "str.h"
8#include "ip.h"
9#include "uint_t.h"
10#include "socket_if.h"
11#include "dns.h"
12#include "taia.h"
13#include "byte.h"
14#include "roots.h"
15#include "fmt.h"
16#include "iopause.h"
17#include "query.h"
18#include "alloc.h"
19#include "response.h"
20#include "sipcache.h"
21#include "ndelay.h"
22#include "log.h"
23#include "clientok.h"
24#include "droproot.h"
25#include "readclose.h"
26#include "curvedns.h"
27
28#define WHO "dnscache"
29
30uint16 dnsport = 53;
31stralloc ifname = {0};
32uint32 ifidx = 0; /* aka scope_id */
33
37char *p = "u";
38
39static int packetquery(char *buf,unsigned int len,char **q,char qtype[2],char qclass[2],char id[2])
40{
41 unsigned int pos;
42 unsigned int ad = 0;
43 char header[12];
44
45 errno = EPROTO;
46 pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return 0;
47 if (header[2] & 128) return 0; /* must not respond to responses */
48 if (!(header[2] & 1)) return 0; /* do not respond to non-recursive queries */
49 if (header[2] & 120) return 0; /* standard query only */
50 if (header[2] & 2) return 0; /* Truncation not allowed */
51 if (header[3] & 32) ad = 1; /* Authenticated data */
52 if (byte_diff(header + 4,2,"\0\1")) return 0;
53
54 pos = dns_packet_getname(buf,len,pos,q); if (!pos) return 0;
55 pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) return 0;
56 pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) return 0;
57 if (byte_diff(qclass,2,DNS_C_IN) && byte_diff(qclass,2,DNS_C_ANY)) return 0;
58 if (!dns_packet_edns0(header,buf,len,pos)) return 0;
59
60 byte_copy(id,2,header);
61 return 1;
62}
63
64static char ipsending[16];
65static char iplistening[16];
66// static char buf[2 * MSGSIZE + 2];
67static char buf[MAXSEGMENT];
68uint64 numqueries = 0;
69
70static int udp53;
71
72static struct udpclient {
73 struct query q;
74 struct taia start;
75 uint64 active; /* query number, if active; otherwise 0 */
76 iopause_fd *io;
77 char ip[16];
78 uint16 port;
79 char id[2];
80 uint32 scope_id;
81} u[QUERY_MAXUDP];
82
83int uactive = 0;
84int eactive = 0;
85
86void u_drop(int j)
87{
88 if (!u[j].active) return;
89 p = "u";
90 log_querydrop(&u[j].active,p);
91 u[j].active = 0; --uactive;
92}
93
94void u_respond(int j)
95{
96 if (!u[j].active) return;
97 response_id(u[j].id);
99 socket_send(udp53,response,response_len,u[j].ip,u[j].port,u[j].scope_id);
100 p = "u";
101 log_querydone(&u[j].active,response_len,p);
102 u[j].active = 0; --uactive;
103}
104
105void u_new(void)
106{
107 int j;
108 int i;
109 struct udpclient *x;
110 int len;
111 static char *q = 0;
112 char qtype[2];
113 char qclass[2];
114
115 for (j = 0; j < QUERY_MAXUDP; ++j)
116 if (!u[j].active)
117 break;
118
119 if (j >= QUERY_MAXUDP) {
120 j = 0;
121 for (i = 1; i < QUERY_MAXUDP; ++i)
122 if (taia_less(&u[i].start,&u[j].start))
123 j = i;
124 errno = ETIMEDOUT;
125 u_drop(j);
126 }
127
128 x = u + j;
129 taia_now(&x->start);
130
131 len = socket_recv(udp53,buf,sizeof(buf),x->ip,&x->port,&x->scope_id);
132 if (len == -1) return;
133 if (len >= sizeof(buf)) return;
134 if (x->port < 1024) if (x->port != 53) return;
135 if (!clientok(x->ip)) {
136 char ipstr[IP6_FMT];
137 if (ip6_isv4mapped(x->ip)) len = ip4_fmt(ipstr,x->ip + 12);
138 else len = ip6_fmt(ipstr,x->ip);
139 ipstr[len] = '\0';
140 logmsg(WHO,99,WARN,B("client blocked: ",ipstr));
141 return;
142 }
143
144 if (!packetquery(buf,len,&q,qtype,qclass,x->id)) return;
145
146 x->active = ++numqueries; ++uactive;
147 p = "u";
148 if (len > MINMSGSIZE) { ++eactive; p = "e"; }
149 log_query(&x->active,x->ip,x->port,x->id,q,qtype,p);
150
151 switch (query_start(&x->q,q,qtype,qclass,ipsending,x->scope_id)) { // FIXME: &x->scope_id
152 case -1: case -2: u_drop(j); return;
153 case 1: u_respond(j);
154 }
155}
156
157static int tcp53;
158
159struct tcpclient {
160 struct query q;
161 struct taia start;
162 struct taia timeout;
163 uint64 active; /* query number or 1, if active; otherwise 0 */
164 iopause_fd *io;
165 char ip[16]; /* send response to this address */
166 uint16 port; /* send response to this port */
167 char id[2];
168 int tcp; /* open TCP socket, if active */
169 int state;
170 char *buf; /* 0, or dynamically allocated of length len */
171 unsigned int len;
172 unsigned int pos;
173 uint32 scope_id;
175int tactive = 0;
176
177/*
178state 1: buf 0; normal state at beginning of TCP connection
179state 2: buf 0; have read 1 byte of query packet length into len
180state 3: buf allocated; have read pos bytes of buf
181state 0: buf 0; handling query in q
182state -1: buf allocated; have written pos bytes
183*/
184
185void t_free(int j)
186{
187 if (!t[j].buf) return;
188 alloc_free(t[j].buf);
189 t[j].buf = 0;
190}
191
192void t_timeout(int j)
193{
194 struct taia now;
195 if (!t[j].active) return;
196 taia_now(&now);
197 taia_uint(&t[j].timeout,10);
198 taia_add(&t[j].timeout,&t[j].timeout,&now);
199}
200
201void t_close(int j)
202{
203 if (!t[j].active) return;
204 t_free(j);
205 log_tcpclose(t[j].ip,t[j].port);
206 close(t[j].tcp);
207 t[j].active = 0; --tactive;
208}
209
210void t_drop(int j)
211{
212 p = "t";
213 log_querydrop(&t[j].active,p);
214 errno = EPIPE;
215 t_close(j);
216}
217
218void t_respond(int j)
219{
220 if (!t[j].active) return;
221 p = "t";
222 log_querydone(&t[j].active,response_len,p);
223 response_id(t[j].id);
224 t[j].len = response_len + 2;
225 t_free(j);
226 t[j].buf = alloc(response_len + 2);
227 if (!t[j].buf) { t_close(j); return; }
228 uint16_pack_big(t[j].buf,response_len);
229 byte_copy(t[j].buf + 2,response_len,response);
230 t[j].pos = 0;
231 t[j].state = -1;
232}
233
234void t_rw(int j)
235{
236 struct tcpclient *x;
237 char *ch;
238 static char *q = 0;
239 unsigned int readsize;
240 char qtype[2];
241 char qclass[2];
242 int r;
243
244 x = t + j;
245 if (x->state == -1) {
246 r = write(x->tcp,x->buf + x->pos,x->len - x->pos);
247 if (r <= 0) { t_close(j); return; }
248 x->pos += r;
249 if (x->pos == x->len) {
250 t_free(j);
251 x->state = 1; /* could drop connection immediately */
252 }
253 return;
254 }
255
256 switch (x->state) {
257 case 1: readsize = 2U; break;
258 case 2: readsize = 1U; break;
259 case 3: readsize = x->len - x->pos; break;
260 default: return; /* impossible */
261 }
262
263 r = read(x->tcp,buf,readsize);
264 if (r == 0) { errno = EPIPE; t_close(j); return; }
265 if (r < 0) { t_close(j); return; }
266
267 ch = buf;
268 if (x->state == 1) {
269 x->len = (unsigned char) *ch++;
270 x->len <<= 8;
271 x->state = 2;
272 if (--r <= 0) return;
273 }
274 if (x->state == 2) {
275 x->len += (unsigned char) *ch;
276 if (!x->len) { errno = EPIPE; t_close(j); return; }
277 x->buf = alloc(x->len);
278 if (!x->buf) { t_close(j); return; }
279 x->pos = 0;
280 x->state = 3;
281 return;
282 }
283
284 if (x->state != 3) return; /* impossible */
285
286 byte_copy(&x->buf[x->pos],r,ch);
287 x->pos += r;
288 if (x->pos < x->len) return;
289
290 if (!packetquery(x->buf,x->len,&q,qtype,qclass,x->id)) { t_close(j); return; }
291
292 x->active = ++numqueries;
293 p = "t";
294 log_query(&x->active,x->ip,x->port,x->id,q,qtype,p);
295 switch (query_start(&x->q,q,qtype,qclass,ipsending,ifidx)) {
296 case -1: case -2: t_drop(j); return;
297 case 1: t_respond(j); return;
298 }
299 t_free(j);
300 x->state = 0;
301}
302
303void t_new(void)
304{
305 int i;
306 int j;
307 int len;
308 struct tcpclient *x;
309
310 for (j = 0; j < QUERY_MAXTCP; ++j)
311 if (!t[j].active)
312 break;
313
314 if (j >= QUERY_MAXTCP) {
315 j = 0;
316 for (i = 1; i < QUERY_MAXTCP; ++i)
317 if (taia_less(&t[i].start,&t[j].start)) j = i;
318 errno = ETIMEDOUT;
319 if (t[j].state == 0)
320 t_drop(j);
321 else
322 t_close(j);
323 }
324
325 x = t + j;
326 taia_now(&x->start);
327
328 x->tcp = socket_accept(tcp53,x->ip,&x->port,&x->scope_id);
329 if (x->tcp == -1) return;
330 if (x->port < 1024) if (x->port != 53) { close(x->tcp); return; }
331 if (!clientok(x->ip)) {
332 char ipstr[IP6_FMT];
333 if (ip6_isv4mapped(x->ip)) len = ip4_fmt(ipstr,x->ip + 12);
334 else len = ip6_fmt(ipstr,x->ip);
335 ipstr[len] = '\0'; // Bugfix Martin C; 10.11.2022
336 logmsg(WHO,99,WARN,B("client blocked: ",ipstr));
337 close(x->tcp);
338 return;
339 }
340 if (ndelay_on(x->tcp) == -1) { close(x->tcp); return; } /* Linux bug */
341
342 x->active = 1; ++tactive;
343 x->state = 1;
344 t_timeout(j);
345
346 log_tcpopen(x->ip,x->port);
347}
348
349
350iopause_fd io[3 + QUERY_MAXUDP + QUERY_MAXTCP];
351iopause_fd *udp53io;
352iopause_fd *tcp53io;
353
354static void doit(void)
355{
356 int j;
357 struct taia deadline;
358 struct taia stamp;
359 int iolen;
360 int r;
361
362 for (;;) {
363 taia_now(&stamp);
364 taia_uint(&deadline,120);
365 taia_add(&deadline,&deadline,&stamp);
366
367 iolen = 0;
368
369 udp53io = io + iolen++;
370 udp53io->fd = udp53;
371 udp53io->events = IOPAUSE_READ;
372
373 tcp53io = io + iolen++;
374 tcp53io->fd = tcp53;
375 tcp53io->events = IOPAUSE_READ;
376
377 for (j = 0; j < QUERY_MAXUDP; ++j)
378 if (u[j].active) {
379 u[j].io = io + iolen++;
380 query_io(&u[j].q,u[j].io,&deadline);
381 }
382
383 for (j = 0; j < QUERY_MAXTCP; ++j)
384 if (t[j].active) {
385 t[j].io = io + iolen++;
386 if (t[j].state == 0)
387 query_io(&t[j].q,t[j].io,&deadline);
388 else {
389 if (taia_less(&t[j].timeout,&deadline)) deadline = t[j].timeout;
390 t[j].io->fd = t[j].tcp;
391 t[j].io->events = (t[j].state > 0) ? IOPAUSE_READ : IOPAUSE_WRITE;
392 }
393 }
394
395 if (iopause(io,iolen,&deadline,&stamp) < 0) {
396 errno = ECONNRESET;
397 logmsg(WHO,errno,FATAL,"IO resources not available");
398 }
399
400 for (j = 0; j < QUERY_MAXUDP; ++j)
401 if (u[j].active) {
402 r = query_get(&u[j].q,u[j].io,&stamp);
403 if (r == -1 || r == -2 || r == -3) { errno = ECONNRESET; u_drop(j); }
404 if (r == 1) u_respond(j);
405 }
406
407 for (j = 0; j < QUERY_MAXTCP; ++j)
408 if (t[j].active) {
409 if (t[j].io->revents) t_timeout(j);
410 if (t[j].state == 0) {
411 r = query_get(&t[j].q,t[j].io,&stamp);
412 if (r == -1 || r == -2 || r == -3) { errno = ECONNRESET; t_drop(j); }
413 if (r == 1) t_respond(j);
414 }
415 else if (t[j].io->revents || taia_less(&t[j].timeout,&stamp))
416 t_rw(j);
417 }
418
419 if (udp53io)
420 if (udp53io->revents)
421 u_new();
422
423 if (tcp53io)
424 if (tcp53io->revents)
425 t_new();
426 }
427}
428
429char seed[128];
430
431int main()
432{
433 char *x;
434 unsigned long cachesize;
435 flagedserver = 0;
436 fallback = 0;
437
438 x = env_get("IP");
439 if (!x)
440 logmsg(WHO,111,ERROR,"$IP not set");
441 if (case_equals(x,"::")) {
442 flagipv6anycast = 1;
443 } else if (case_equals(x,":0")) {
444 flagdualstack = 1;
445 byte_copy(x,2,"::");
446 ifidx = 0;
447 }
448 if (!ip6_ifscan(x,iplistening,&ifname))
449 logmsg(WHO,101,SYNTAX,B("unable to parse IP address: ",x));
450
451 if (ifname.len > 1) ifidx = socket_getifidx(ifname.s);
452
453 if (ip6_isv4mapped(iplistening))
454 udp53 = socket_udp4();
455 else
456 udp53 = socket_udp();
457 if (udp53 == -1)
458 logmsg(WHO,111,FATAL,"unable to create UDP socket");
459
460 if (flagdualstack) socket_dualstack(udp53);
461 if (flagipv6anycast) socket_ip6anycast(udp53);
462 if (socket_bind_reuse(udp53,iplistening,dnsport,ifidx) == -1)
463 logmsg(WHO,111,FATAL,"unable to bind to UDP socket");
464
465 if (ip6_isv4mapped(iplistening))
466 tcp53 = socket_tcp4();
467 else
468 tcp53 = socket_tcp6();
469 if (tcp53 == -1)
470 logmsg(WHO,111,FATAL,"unable to create TCP socket");
471
472 if (flagdualstack) socket_dualstack(tcp53);
473 if (flagipv6anycast) socket_ip6anycast(tcp53);
474 if (socket_bind_reuse(tcp53,iplistening,dnsport,ifidx) == -1)
475 logmsg(WHO,111,FATAL,"unable to bind to TCP socket");
476
477 droproot(WHO);
478
479 socket_tryreservein(udp53,131072);
480
481 byte_zero(seed,sizeof(seed));
482 read(0,seed,sizeof(seed));
484 close(0);
485 query_init();
486
487 x = env_get("IPSEND");
488 if (!x)
489 logmsg(WHO,111,ERROR,"$IPSEND not set");
490 if (!ip6_ifscan(x,ipsending,&ifname))
491 logmsg(WHO,100,SYNTAX,B("unable to parse IP address: ",x));
492
493 x = env_get("CACHESIZE");
494 if (!x)
495 logmsg(WHO,111,ERROR,"$CACHESIZE not set");
496 scan_ulong(x,&cachesize);
497 if (!cache_init(cachesize))
498 logmsg(WHO,111,FATAL,B("not enough memory for cache of size: ",x));
499
500 if (env_get("HIDETTL"))
502 if (env_get("FORWARDONLY"))
504 if (env_get("USETXTFORMAT"))
506 if (env_get("USETEXTFORMAT"))
508 x = env_get("UZ5FALLBACK");
509 if (x) scan_uint(x,&fallback);
510 if (env_get("FLAGEDSERVER"))
511 flagedserver = 1;
512
513
514 if (!roots_init())
515 logmsg(WHO,111,ERROR,"unable to read servers");
516
517 if (socket_listen(tcp53,TCP_BACKLOG) == -1)
518 logmsg(WHO,111,FATAL,"unable to listen on TCP socket");
519
520 log_startup(iplistening,ifidx,ipsending,MSGSIZE);
521 doit();
522}
unsigned int doit(char *buf, unsigned int len, unsigned int pos)
Definition: axfr-get.c:131
unsigned long port
Definition: axfrdns.c:126
struct tai now
Definition: axfrdns.c:129
char ip[16]
Definition: axfrdns.c:125
uint16 len
Definition: axfrdns.c:319
char buf[MSGSIZE]
Definition: axfrdns.c:318
int clientok(char ip[16])
Definition: clientok.c:11
unsigned int fallback
Definition: curvedns.c:23
unsigned int flagedserver
Definition: curvedns.c:22
#define DNS_C_IN
Definition: dns.h:53
#define MSGSIZE
Definition: dns.h:38
#define MAXSEGMENT
Definition: dns.h:41
#define TCP_BACKLOG
Definition: dns.h:46
#define DNS_C_ANY
Definition: dns.h:54
#define MINMSGSIZE
Definition: dns.h:39
unsigned int dns_packet_getname(const char *buf, unsigned int len, unsigned int pos, char **d)
Definition: dns_packet.c:35
unsigned int dns_packet_copy(const char *buf, unsigned int len, unsigned int pos, char *out, unsigned int outlen)
Definition: dns_packet.c:8
void dns_random_init(const char data[128])
Definition: dns_random.c:37
uint64 numqueries
Definition: dnscache.c:68
int flagipv6anycast
Definition: dnscache.c:36
void t_close(int j)
Definition: dnscache.c:201
void u_new(void)
Definition: dnscache.c:105
uint32 ifidx
Definition: dnscache.c:32
void t_respond(int j)
Definition: dnscache.c:218
void u_respond(int j)
Definition: dnscache.c:94
iopause_fd * udp53io
Definition: dnscache.c:351
void t_new(void)
Definition: dnscache.c:303
void u_drop(int j)
Definition: dnscache.c:86
char * p
Definition: dnscache.c:37
int flagusetxtformat
Definition: dnscache.c:34
iopause_fd * tcp53io
Definition: dnscache.c:352
void t_timeout(int j)
Definition: dnscache.c:192
int uactive
Definition: dnscache.c:83
void t_free(int j)
Definition: dnscache.c:185
stralloc ifname
Definition: dnscache.c:31
uint16 dnsport
Definition: dnscache.c:30
int eactive
Definition: dnscache.c:84
void t_drop(int j)
Definition: dnscache.c:210
#define WHO
Definition: dnscache.c:28
char seed[128]
Definition: dnscache.c:429
int main()
Definition: dnscache.c:431
int flagdualstack
Definition: dnscache.c:35
struct tcpclient t[QUERY_MAXTCP]
iopause_fd io[3+QUERY_MAXUDP+QUERY_MAXTCP]
Definition: dnscache.c:350
void t_rw(int j)
Definition: dnscache.c:234
int tactive
Definition: dnscache.c:175
int iolen
Definition: dnsfilter.c:46
struct line * x
char ipstr[IP6_FMT]
Definition: dnstrace.c:31
void droproot(const char *fatal)
Definition: droproot.c:8
unsigned int dns_packet_edns0(const char header[12], const char *buf, const int len, unsigned int pos)
Definition: edns0.c:21
void start(const char *s)
Definition: generic-conf.c:41
void log_querydrop(uint64 *, const char *)
Definition: log.c:127
void log_tcpopen(const char *, unsigned int)
void log_query(uint64 *, const char *, unsigned int, const char *, const char *, const char *, const char *)
void log_startup(const char *, uint32, const char *, int)
void log_querydone(uint64 *, unsigned int, const char *)
Definition: log.c:120
void log_tcpclose(const char *, unsigned int)
#define QUERY_MAXTCP
Definition: query.h:14
void query_init(void)
Definition: query.c:23
int query_start(struct query *, char *, char *, char *, char *, uint32)
void query_io(struct query *, iopause_fd *, struct taia *)
Definition: query.c:1203
#define QUERY_MAXUDP
Definition: query.h:13
int query_get(struct query *, iopause_fd *, struct taia *)
Definition: query.c:1192
void query_forwardonly(void)
Definition: query.c:36
void response_hidettl(void)
Definition: response.c:70
void response_id(const char *)
char response[]
Definition: response.c:6
void response_tc(void)
Definition: response.c:119
unsigned int response_len
Definition: response.c:7
int roots_init(void)
Definition: roots.c:127
int cache_init(unsigned int)
Definition: sipcache.c:177
Definition: query.h:56
struct query q
Definition: dnscache.c:160
uint32 scope_id
Definition: dnscache.c:173
struct taia timeout
Definition: dnscache.c:162
char * buf
Definition: dnscache.c:170
uint16 port
Definition: dnscache.c:166
unsigned int len
Definition: dnscache.c:171
iopause_fd * io
Definition: dnscache.c:164
int state
Definition: dnscache.c:169
char ip[16]
Definition: dnscache.c:165
uint64 active
Definition: dnscache.c:163
unsigned int pos
Definition: dnscache.c:172
struct taia start
Definition: dnscache.c:161
int tcp
Definition: dnscache.c:168