39static int packetquery(
char *buf,
unsigned int len,
char **q,
char qtype[2],
char qclass[2],
char id[2])
47 if (header[2] & 128)
return 0;
48 if (!(header[2] & 1))
return 0;
49 if (header[2] & 120)
return 0;
50 if (header[2] & 2)
return 0;
51 if (header[3] & 32) ad = 1;
52 if (byte_diff(header + 4,2,
"\0\1"))
return 0;
60 byte_copy(
id,2,header);
64static char ipsending[16];
65static char iplistening[16];
72static struct udpclient {
88 if (!u[j].active)
return;
98 if (!u[j].active)
return;
107 if (ip6_isv4mapped(u[j].
ip))
108 ip4_fmt(
d,u[j].
ip + 12);
111 logmsg(
WHO,errno,WARN,B(
"sending reply to ",
d,
" failed."));
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;
149 if (ip6_isv4mapped(
x->ip))
len = ip4_fmt(
ipstr,
x->ip + 12);
152 logmsg(
WHO,99,WARN,B(
"client blocked: ",
ipstr));
156 if (!packetquery(
buf,
len,&q,qtype,qclass,
x->id))
return;
163 switch (
query_start(&
x->q,q,qtype,qclass,ipsending,
x->scope_id)) {
164 case -1:
case -2:
u_drop(j);
return;
199 if (!
t[j].
buf)
return;
200 alloc_free(
t[j].
buf);
207 if (!
t[j].active)
return;
209 taia_uint(&
t[j].timeout,10);
210 taia_add(&
t[j].timeout,&
t[j].timeout,&
now);
215 if (!
t[j].active)
return;
232 if (!
t[j].active)
return;
251 unsigned int readsize;
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; }
261 if (
x->pos ==
x->len) {
269 case 1: readsize = 2U;
break;
270 case 2: readsize = 1U;
break;
271 case 3: readsize =
x->len -
x->pos;
break;
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; }
281 x->len = (
unsigned char) *ch++;
284 if (--r <= 0)
return;
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; }
296 if (
x->state != 3)
return;
298 byte_copy(&
x->buf[
x->pos],r,ch);
300 if (
x->pos <
x->len)
return;
302 if (!packetquery(
x->buf,
x->len,&
q,qtype,qclass,
x->id)) {
t_close(j);
return; }
308 case -1:
case -2:
t_drop(j);
return;
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; }
345 if (ip6_isv4mapped(
x->ip))
len = ip4_fmt(
ipstr,
x->ip + 12);
348 logmsg(
WHO,99,WARN,B(
"client blocked: ",
ipstr));
352 if (ndelay_on(
x->tcp) == -1) { close(
x->tcp);
return; }
366static void doit(
void)
369 struct taia deadline;
376 taia_uint(&deadline,120);
377 taia_add(&deadline,&deadline,&stamp);
383 udp53io->events = IOPAUSE_READ;
387 tcp53io->events = IOPAUSE_READ;
401 if (taia_less(&
t[j].timeout,&deadline)) deadline =
t[j].
timeout;
403 t[j].
io->events = (
t[j].
state > 0) ? IOPAUSE_READ : IOPAUSE_WRITE;
407 if (iopause(
io,
iolen,&deadline,&stamp) < 0) {
409 logmsg(
WHO,errno,FATAL,
"IO resources not available");
415 if (r == -1 || r == -2 || r == -3) { errno = ECONNRESET;
u_drop(j); }
422 if (
t[j].state == 0) {
424 if (r == -1 || r == -2 || r == -3) { errno = ECONNRESET;
t_drop(j); }
427 else if (
t[j].
io->revents || taia_less(&
t[j].timeout,&stamp))
446 unsigned long cachesize;
452 logmsg(
WHO,111,ERROR,
"$IP not set");
453 if (case_equals(
x,
"::")) {
455 }
else if (case_equals(
x,
":0")) {
461 if (!ip6_ifscan(
x,iplistening,&
ifname))
462 logmsg(
WHO,101,SYNTAX,B(
"unable to parse IP address: ",
x));
466 if (ip6_isv4mapped(iplistening))
467 udp53 = socket_udp4();
469 udp53 = socket_udp();
471 logmsg(
WHO,111,FATAL,
"unable to create UDP socket");
475 if (socket_bind_reuse(udp53,iplistening,
dnsport,
ifidx) == -1)
476 logmsg(
WHO,111,FATAL,
"unable to bind to UDP socket");
478 if (ip6_isv4mapped(iplistening))
479 tcp53 = socket_tcp4();
481 tcp53 = socket_tcp6();
483 logmsg(
WHO,111,FATAL,
"unable to create TCP socket");
487 if (socket_bind_reuse(tcp53,iplistening,
dnsport,
ifidx) == -1)
488 logmsg(
WHO,111,FATAL,
"unable to bind to TCP socket");
492 socket_tryreservein(udp53,131072);
500 x = env_get(
"IPSEND");
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));
506 x = env_get(
"CACHESIZE");
508 logmsg(
WHO,111,ERROR,
"$CACHESIZE not set");
509 scan_dnum(
x,&cachesize);
511 logmsg(
WHO,111,FATAL,B(
"not enough memory for cache of size: ",
x));
513 if (env_get(
"HIDETTL"))
515 if (env_get(
"USETXTFORMAT"))
517 if (env_get(
"USETEXTFORMAT"))
519 x = env_get(
"UZ5FALLBACK");
521 if (env_get(
"FLAGEDSERVER"))
523 if (env_get(
"DNSOPTRR"))
526 x = env_get(
"FORWARDONLY");
530 logmsg(
WHO,111,ERROR,
"unable to read servers");
533 logmsg(
WHO,111,FATAL,
"unable to listen on TCP socket");
unsigned int doit(char *buf, unsigned int len, unsigned int pos)
int clientok(char ip[16])
unsigned int flagedserver
unsigned int dns_packet_getname(const char *buf, unsigned int len, unsigned int pos, char **d)
unsigned int dns_packet_copy(const char *buf, unsigned int len, unsigned int pos, char *out, unsigned int outlen)
void dns_random_init(const char data[128])
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 d(const char *home, const char *subdir, int uid, int gid, int mode)
void log_tcpopen(const char[16], unsigned int)
void log_querydrop(uint64 *, const char *)
void log_startup(const char[16], uint32, const char[16], int, char *)
void log_query(uint64 *, const char[16], unsigned int, const char[2], const char *, const char[2], const char *)
void log_tcpclose(const char[16], unsigned int)
void log_querydone(uint64 *, unsigned int, const char *)
void query_io(struct query *, iopause_fd *, struct taia *)
int query_start(struct query *, char *, char[2], char[2], char[16], uint32)
int query_get(struct query *, iopause_fd *, struct taia *)
void query_forwardonly(void)
void response_id(const char[2])
void response_hidettl(void)
unsigned int response_len
int cache_init(unsigned int)