44static int packetquery(
char *buf,
unsigned int len,
char **q,
char qtype[2],
char qclass[2],
char id[2])
52 if (header[2] & 128)
return 0;
53 if (!(header[2] & 1))
return 0;
54 if (header[2] & 120)
return 0;
55 if (header[2] & 2)
return 0;
56 if (header[3] & 32) ad = 1;
57 if (byte_diff(header + 4,2,
"\0\1"))
return 0;
65 byte_copy(
id,2,header);
69static char ipsending[16];
70static char iplistening[16];
76static struct udpclient {
92 if (!u[j].active)
return;
103 if (!u[j].active)
return;
111 if (ip6_isv4mapped(u[j].
ip))
112 ip4_fmt(
d,u[j].
ip + 12);
115 logmsg(
WHO,errno,WARN,B(
"sending reply to ",
d,
" failed."));
149 len = socket_recv(udp53,
buf,
sizeof(
buf),
x->ip,&
x->port,&
x->scope_id);
150 if (
len == -1)
return;
151 if (
len >=
sizeof(
buf))
return;
152 if (
x->port < 1024)
if (
x->port !=
DNSPORT)
return;
155 if (ip6_isv4mapped(
x->ip))
len = ip4_fmt(
ipstr,
x->ip + 12);
158 logmsg(
WHO,99,WARN,B(
"client blocked: ",
ipstr));
162 if (!packetquery(
buf,
len,&q,qtype,qclass,
x->id))
return;
169 switch (
query_start(&
x->q,q,qtype,qclass,ipsending,
x->scope_id)) {
170 case -1:
case -2:
u_drop(j);
return;
205 if (!
t[j].
buf)
return;
206 alloc_free(
t[j].
buf);
213 if (!
t[j].active)
return;
215 taia_uint(&
t[j].timeout,10);
216 taia_add(&
t[j].timeout,&
t[j].timeout,&
now);
221 if (!
t[j].active)
return;
237 if (!
t[j].active)
return;
255 unsigned int readsize;
261 if (
x->state == -1) {
262 r = write(
x->tcp,
x->buf +
x->pos,
x->len -
x->pos);
263 if (r <= 0) {
t_close(j);
return; }
265 if (
x->pos ==
x->len) {
273 case 1: readsize = 2U;
break;
274 case 2: readsize = 1U;
break;
275 case 3: readsize =
x->len -
x->pos;
break;
279 r = read(
x->tcp,
buf,readsize);
280 if (r == 0) { errno = EPIPE;
t_close(j);
return; }
281 if (r < 0) {
t_close(j);
return; }
285 x->len = (
unsigned char) *ch++;
288 if (--r <= 0)
return;
291 x->len += (
unsigned char) *ch;
292 if (!
x->len) { errno = EPIPE;
t_close(j);
return; }
293 x->buf = alloc(
x->len);
294 if (!
x->buf) {
t_close(j);
return; }
300 if (
x->state != 3)
return;
302 byte_copy(&
x->buf[
x->pos],r,ch);
304 if (
x->pos <
x->len)
return;
306 if (!packetquery(
x->buf,
x->len,&
q,qtype,qclass,
x->id)) {
t_close(j);
return; }
310 switch (
query_start(&
x->q,
q,qtype,qclass,ipsending,
x->scope_id)) {
311 case -1:
case -2:
t_drop(j);
return;
343 x->tcp = socket_accept(tcp53,
x->ip,&
x->port,&
x->scope_id);
344 if (
x->tcp == -1)
return;
345 if (
x->port < 1024)
if (
x->port !=
DNSPORT) { close(
x->tcp);
return; }
348 if (ip6_isv4mapped(
x->ip))
len = ip4_fmt(
ipstr,
x->ip + 12);
351 logmsg(
WHO,99,WARN,B(
"client blocked: ",
ipstr));
355 if (ndelay_on(
x->tcp) == -1) { close(
x->tcp);
return; }
369static void doit(
void)
372 struct taia deadline;
379 taia_uint(&deadline,120);
380 taia_add(&deadline,&deadline,&stamp);
386 udp53io->events = IOPAUSE_READ;
390 tcp53io->events = IOPAUSE_READ;
404 if (taia_less(&
t[j].timeout,&deadline)) deadline =
t[j].
timeout;
406 t[j].
io->events = (
t[j].
state > 0) ? IOPAUSE_READ : IOPAUSE_WRITE;
410 if (iopause(
io,
iolen,&deadline,&stamp) < 0) {
412 logmsg(
WHO,errno,FATAL,
"IO resources not available");
418 if (r == -1 || r == -2 || r == -3) { errno = ECONNRESET;
u_drop(j); }
425 if (
t[j].state == 0) {
427 if (r == -1 || r == -2 || r == -3) { errno = ECONNRESET;
t_drop(j); }
430 else if (
t[j].
io->revents || taia_less(&
t[j].timeout,&stamp))
449 unsigned long cachesize;
454 for (
int i = 0; i <
MAXOPT; ++i) opt[i] = 0;
458 logmsg(
WHO,111,ERROR,
"$IP not set");
459 if (case_equals(
x,
"::")) {
462 }
else if (case_equals(
x,
":0")) {
468 if (!ip6_ifscan(
x,iplistening,&
ifname))
469 logmsg(
WHO,101,SYNTAX,B(
"unable to parse IP address: ",
x));
473 if (ip6_isv4mapped(iplistening))
474 udp53 = socket_udp4();
476 udp53 = socket_udp();
478 logmsg(
WHO,111,FATAL,
"unable to create UDP socket");
482 if (socket_bind_reuse(udp53,iplistening,
dnsport,
ifidx) == -1)
483 logmsg(
WHO,111,FATAL,
"unable to bind to UDP socket");
485 if (ip6_isv4mapped(iplistening))
486 tcp53 = socket_tcp4();
488 tcp53 = socket_tcp6();
490 logmsg(
WHO,111,FATAL,
"unable to create TCP socket");
494 if (socket_bind_reuse(tcp53,iplistening,
dnsport,
ifidx) == -1)
495 logmsg(
WHO,111,FATAL,
"unable to bind to TCP socket");
499 socket_tryreservein(udp53,131072);
507 x = env_get(
"IPSEND");
509 logmsg(
WHO,111,ERROR,
"$IPSEND not set");
510 if (!ip6_ifscan(
x,ipsending,&
ifname))
511 logmsg(
WHO,100,SYNTAX,B(
"unable to parse IP address: ",
x));
513 x = env_get(
"CACHESIZE");
515 logmsg(
WHO,111,ERROR,
"$CACHESIZE not set");
516 scan_dnum(
x,&cachesize);
518 logmsg(
WHO,111,FATAL,B(
"not enough memory for cache of size: ",
x));
520 x = env_get(
"UDPSIZE");
523 if (env_get(
"HIDETTL"))
525 if (env_get(
"USETXTFORMAT"))
528 x = env_get(
"UZ5FALLBACK");
531 if (env_get(
"FLAGEDSERVER"))
534 x = env_get(
"DNSOPTRR");
537 x = env_get(
"FORWARDONLY");
541 logmsg(
WHO,111,ERROR,
"unable to read servers");
544 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 udp_msgsize(void)
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 *server)
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_query(uint64 *, const char[16], unsigned int, const char[2], const char *, const char[2])
void log_querydrop(uint64 *)
void log_querydone(uint64 *, unsigned int)
void log_tcpclose(const char[16], unsigned int)
void log_startup(const char[16], uint32, const char[16], int, int[MAXOPT])
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)