10 #include "socket_if.h"
25 #include "readclose.h"
33 #define WHO "dnscache"
42 static int packetquery(
char *
buf,
unsigned int len,
char **q,
char qtype[2],
char qclass[2],
char id[2])
50 if (header[2] & 128)
return 0;
51 if (!(header[2] & 1))
return 0;
52 if (header[2] & 120)
return 0;
53 if (header[2] & 2)
return 0;
54 if (header[3] & 32) ad = 1;
55 if (byte_diff(header + 4,2,
"\0\1"))
return 0;
63 byte_copy(
id,2,header);
67 static char ipsending[16];
68 static char iplistening[16];
74 static struct udpclient {
89 if (!
u[j].active)
return;
97 if (!
u[j].active)
return;
135 len = socket_recv(udp53,
buf,
sizeof(
buf),
x->ip,&
x->port,&
x->scope_id);
136 if (
len == -1)
return;
137 if (
len >=
sizeof(
buf))
return;
138 if (
x->port < 1024)
if (
x->port != 53)
return;
141 if (ip6_isv4mapped(
x->ip))
len = ip4_fmt(
ipstr,
x->ip + 12);
144 logmsg(
WHO,-99,WARN,B(
"client blocked: ",
ipstr));
148 if (!packetquery(
buf,
len,&q,qtype,qclass,
x->id))
return;
156 case -1:
case -2:
case -3:
u_drop(j);
return;
191 if (!
t[j].
buf)
return;
192 alloc_free(
t[j].
buf);
199 if (!
t[j].active)
return;
201 taia_uint(&
t[j].timeout,10);
202 taia_add(&
t[j].timeout,&
t[j].timeout,&
now);
207 if (!
t[j].active)
return;
224 if (!
t[j].active)
return;
243 unsigned int readsize;
249 if (
x->state == -1) {
250 r = write(
x->tcp,
x->buf +
x->pos,
x->len -
x->pos);
251 if (r <= 0) {
t_close(j);
return; }
253 if (
x->pos ==
x->len) {
260 r = read(
x->tcp,&ch,1);
262 case 1: readsize = 2U;
break;
263 case 2: readsize = 1U;
break;
264 case 3: readsize =
x->len -
x->pos;
break;
267 r = read(
x->tcp,
buf,readsize);
269 if (r == 0) { errno = EPIPE;
t_close(j);
return; }
270 if (r < 0) {
t_close(j);
return; }
274 x->len = (
unsigned char) *ch++;
277 if (--r <= 0)
return;
280 x->len += (
unsigned char) *ch;
281 if (
x->len < 12) { errno = EPROTO;
t_close(j);
return; }
282 x->buf = alloc(
x->len);
283 if (!
x->buf) {
t_close(j);
return; }
289 if (
x->state != 3)
return;
291 x->buf[
x->pos++] = *ch;
292 byte_copy(&
x->buf[
x->pos],r,ch);
294 if (
x->pos <
x->len)
return;
296 if (!packetquery(
x->buf,
x->len,&
q,qtype,qclass,
x->id)) {
t_close(j);
return; }
302 case -1:
case -2:
case -3:
t_drop(j);
return;
335 x->tcp = socket_accept(tcp53,
x->ip,&
x->port,&
x->scope_id);
336 if (
x->tcp == -1)
return;
337 if (
x->port < 1024)
if (
x->port != 53) { close(
x->tcp);
return; }
340 if (ip6_isv4mapped(
x->ip))
len = ip4_fmt(
ipstr,
x->ip + 12);
343 logmsg(
WHO,-99,WARN,B(
"client blocked: ",
ipstr));
347 if (ndelay_on(
x->tcp) == -1) { close(
x->tcp);
return; }
361 static void doit(
void)
364 struct taia deadline;
371 taia_uint(&deadline,120);
372 taia_add(&deadline,&deadline,&stamp);
378 udp53io->events = IOPAUSE_READ;
382 tcp53io->events = IOPAUSE_READ;
396 if (taia_less(&
t[j].timeout,&deadline)) deadline =
t[j].
timeout;
398 t[j].
io->events = (
t[j].
state > 0) ? IOPAUSE_READ : IOPAUSE_WRITE;
402 if (iopause(
io,
iolen,&deadline,&stamp) < 0) {
404 logmsg(
WHO,errno,FATAL,
"IO resources not available");
410 if (r == -1 || r == -2 || r == -3) { errno = ECONNRESET;
u_drop(j); }
417 if (
t[j].state == 0) {
419 if (r == -1 || r == -2 || r == -3) { errno = ECONNRESET;
t_drop(j); }
422 else if (
t[j].
io->revents || taia_less(&
t[j].timeout,&stamp))
441 unsigned long cachesize;
445 logmsg(
WHO,111,ERROR,
"$IP not set");
446 if (case_equals(
x,
"::")) {
448 }
else if (case_equals(
x,
":0")) {
452 if (!ip6_ifscan(
x,iplistening,&
ifname))
453 logmsg(
WHO,101,SYNTAX,B(
"unable to parse IP address: ",
x));
456 if (ip6_isv4mapped(iplistening))
457 udp53 = socket_udp4();
459 udp53 = socket_udp();
461 logmsg(
WHO,111,FATAL,
"unable to create UDP socket");
465 if (socket_bind_reuse(udp53,iplistening,
dnsport,
ifidx) == -1)
466 logmsg(
WHO,111,FATAL,
"unable to bind to UDP socket");
468 if (ip6_isv4mapped(iplistening))
469 tcp53 = socket_tcp4();
471 tcp53 = socket_tcp();
473 logmsg(
WHO,111,FATAL,
"unable to create TCP socket");
477 if (socket_bind_reuse(tcp53,iplistening,
dnsport,
ifidx) == -1)
478 logmsg(
WHO,111,FATAL,
"unable to bind to TCP socket");
482 socket_tryreservein(udp53,131072);
490 x = env_get(
"IPSEND");
492 logmsg(
WHO,111,ERROR,
"$IPSEND not set");
493 if (!ip6_ifscan(
x,ipsending,&
ifname))
494 logmsg(
WHO,100,SYNTAX,B(
"unable to parse IP address: ",
x));
496 x = env_get(
"CACHESIZE");
498 logmsg(
WHO,111,ERROR,
"$CACHESIZE not set");
499 scan_ulong(
x,&cachesize);
501 logmsg(
WHO,111,FATAL,B(
"not enough memory for cache of size: ",
x));
503 if (env_get(
"HIDETTL"))
505 if (env_get(
"FORWARDONLY"))
507 if (env_get(
"USETEXTFORMAT"))
509 x = env_get(
"UZ5FALLBACK");
513 if (env_get(
"FLAGEDSERVER"))
518 logmsg(
WHO,111,ERROR,
"unable to read servers");
520 if (socket_listen(tcp53,20) == -1)
521 logmsg(
WHO,111,FATAL,
"unable to listen on TCP socket");
unsigned int doit(char *buf, unsigned int len, unsigned int pos)
int cache_init(unsigned int cachesize)
int clientok(char ip[16])
unsigned int dns_packet_copy(const char *, unsigned int, unsigned int, char *, unsigned int)
unsigned int dns_packet_getname(const char *, unsigned int, unsigned int, char **)
void dns_random_init(const char *)
struct tcpclient t[QUERY_MAXTCP]
iopause_fd io[3+QUERY_MAXUDP+QUERY_MAXTCP]
void droproot(const char *fatal)
unsigned int dns_packet_edns0(const char header[12], const char *buf, const int len, unsigned int pos)
void start(const char *s)
void log_tcpclose(const char client[16], unsigned int port)
void log_tcpopen(const char client[16], unsigned int port)
void log_querydone(uint64 *qnum, unsigned int len, const char *p)
void log_startup(const char listip[16], uint32 scope, const char sendip[16], int size)
void log_query(uint64 *qnum, const char client[16], unsigned int port, const char id[2], const char *q, const char qtype[2], const char *p)
void log_querydrop(uint64 *qnum, const char *p)
void query_io(struct query *z, iopause_fd *x, struct taia *deadline)
int query_get(struct query *z, iopause_fd *x, struct taia *stamp)
void query_forwardonly(void)
int query_start(struct query *z, char *dn, char type[2], char class[2], char localip[16], uint32 scope_id)
void response_hidettl(void)
void response_id(const char id[2])
unsigned int max_response_len
unsigned int response_len