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