Changeset View
Changeset View
Standalone View
Standalone View
src/seeder/dns.cpp
Show First 20 Lines • Show All 321 Lines • ▼ Show 20 Lines | static ssize_t dnshandle(dns_opt_t *opt, const uint8_t *inbuf, size_t insize, | ||||
outbuf[1] = inbuf[1]; | outbuf[1] = inbuf[1]; | ||||
// copy flags; | // copy flags; | ||||
outbuf[2] = inbuf[2]; | outbuf[2] = inbuf[2]; | ||||
outbuf[3] = inbuf[3]; | outbuf[3] = inbuf[3]; | ||||
// clear error | // clear error | ||||
outbuf[3] &= ~15; | outbuf[3] &= ~15; | ||||
// check qr | // check qr | ||||
if (inbuf[2] & 128) { | if (inbuf[2] & 128) { | ||||
/* printf("Got response?\n"); */ | /* fprintf(stdout, "Got response?\n"); */ | ||||
error = 1; | error = 1; | ||||
goto error; | goto error; | ||||
} | } | ||||
// check opcode | // check opcode | ||||
if (((inbuf[2] & 120) >> 3) != 0) { | if (((inbuf[2] & 120) >> 3) != 0) { | ||||
/* printf("Opcode nonzero?\n"); */ | /* fprintf(stdout, "Opcode nonzero?\n"); */ | ||||
error = 4; | error = 4; | ||||
goto error; | goto error; | ||||
} | } | ||||
// unset TC | // unset TC | ||||
outbuf[2] &= ~2; | outbuf[2] &= ~2; | ||||
// unset RA | // unset RA | ||||
outbuf[3] &= ~128; | outbuf[3] &= ~128; | ||||
// check questions | // check questions | ||||
nquestion = (inbuf[4] << 8) + inbuf[5]; | nquestion = (inbuf[4] << 8) + inbuf[5]; | ||||
if (nquestion == 0) { | if (nquestion == 0) { | ||||
/* printf("No questions?\n"); */ | /* fprintf(stdout, "No questions?\n"); */ | ||||
error = 0; | error = 0; | ||||
goto error; | goto error; | ||||
} | } | ||||
if (nquestion > 1) { | if (nquestion > 1) { | ||||
/* printf("Multiple questions %i?\n", nquestion); */ | /* fprintf(stdout, "Multiple questions %i?\n", nquestion); */ | ||||
error = 4; | error = 4; | ||||
goto error; | goto error; | ||||
} | } | ||||
{ | { | ||||
const uint8_t *inpos = inbuf + 12; | const uint8_t *inpos = inbuf + 12; | ||||
const uint8_t *inend = inbuf + insize; | const uint8_t *inend = inbuf + insize; | ||||
char name[256]; | char name[256]; | ||||
Show All 38 Lines | if (nquestion > 1) { | ||||
int typ = (inpos[0] << 8) + inpos[1]; | int typ = (inpos[0] << 8) + inpos[1]; | ||||
int cls = (inpos[2] << 8) + inpos[3]; | int cls = (inpos[2] << 8) + inpos[3]; | ||||
inpos += 4; | inpos += 4; | ||||
uint8_t *outpos = outbuf + (inpos - inbuf); | uint8_t *outpos = outbuf + (inpos - inbuf); | ||||
uint8_t *outend = outbuf + BUFLEN; | uint8_t *outend = outbuf + BUFLEN; | ||||
// printf("DNS: Request host='%s' type=%i class=%i\n", name, typ, | // fprintf(stdout, "DNS: Request host='%s' type=%i class=%i\n", name, | ||||
// cls); | // typ, cls); | ||||
// calculate max size of authority section | // calculate max size of authority section | ||||
if (!((typ == TYPE_NS || typ == QTYPE_ANY) && | if (!((typ == TYPE_NS || typ == QTYPE_ANY) && | ||||
(cls == CLASS_IN || cls == QCLASS_ANY))) { | (cls == CLASS_IN || cls == QCLASS_ANY))) { | ||||
// authority section will be necessary, either NS or SOA | // authority section will be necessary, either NS or SOA | ||||
uint8_t *newpos = outpos; | uint8_t *newpos = outpos; | ||||
write_record_ns(&newpos, outend, "", offset, CLASS_IN, 0, opt->ns); | write_record_ns(&newpos, outend, "", offset, CLASS_IN, 0, opt->ns); | ||||
max_auth_size = newpos - outpos; | max_auth_size = newpos - outpos; | ||||
newpos = outpos; | newpos = outpos; | ||||
write_record_soa(&newpos, outend, "", offset, CLASS_IN, opt->nsttl, | write_record_soa(&newpos, outend, "", offset, CLASS_IN, opt->nsttl, | ||||
opt->ns, opt->mbox, time(NULL), 604800, 86400, | opt->ns, opt->mbox, time(NULL), 604800, 86400, | ||||
2592000, 604800); | 2592000, 604800); | ||||
if (max_auth_size < newpos - outpos) | if (max_auth_size < newpos - outpos) | ||||
max_auth_size = newpos - outpos; | max_auth_size = newpos - outpos; | ||||
// printf("Authority section will claim %i bytes max\n", | // fprintf(stdout, "Authority section will claim %i bytes max\n", | ||||
// max_auth_size); | // max_auth_size); | ||||
} | } | ||||
// Answer section | // Answer section | ||||
// NS records | // NS records | ||||
if ((typ == TYPE_NS || typ == QTYPE_ANY) && | if ((typ == TYPE_NS || typ == QTYPE_ANY) && | ||||
(cls == CLASS_IN || cls == QCLASS_ANY)) { | (cls == CLASS_IN || cls == QCLASS_ANY)) { | ||||
int ret2 = write_record_ns(&outpos, outend - max_auth_size, "", | int ret2 = write_record_ns(&outpos, outend - max_auth_size, "", | ||||
offset, CLASS_IN, opt->nsttl, opt->ns); | offset, CLASS_IN, opt->nsttl, opt->ns); | ||||
// printf("wrote NS record: %i\n", ret2); | // fprintf(stdout, "wrote NS record: %i\n", ret2); | ||||
if (!ret2) { | if (!ret2) { | ||||
outbuf[7]++; | outbuf[7]++; | ||||
have_ns++; | have_ns++; | ||||
} | } | ||||
} | } | ||||
// SOA records | // SOA records | ||||
if ((typ == TYPE_SOA || typ == QTYPE_ANY) && | if ((typ == TYPE_SOA || typ == QTYPE_ANY) && | ||||
(cls == CLASS_IN || cls == QCLASS_ANY) && opt->mbox) { | (cls == CLASS_IN || cls == QCLASS_ANY) && opt->mbox) { | ||||
int ret2 = | int ret2 = | ||||
write_record_soa(&outpos, outend - max_auth_size, "", offset, | write_record_soa(&outpos, outend - max_auth_size, "", offset, | ||||
CLASS_IN, opt->nsttl, opt->ns, opt->mbox, | CLASS_IN, opt->nsttl, opt->ns, opt->mbox, | ||||
time(NULL), 604800, 86400, 2592000, 604800); | time(NULL), 604800, 86400, 2592000, 604800); | ||||
// printf("wrote SOA record: %i\n", ret2); | // fprintf(stdout, "wrote SOA record: %i\n", ret2); | ||||
if (!ret2) { | if (!ret2) { | ||||
outbuf[7]++; | outbuf[7]++; | ||||
} | } | ||||
} | } | ||||
// A/AAAA records | // A/AAAA records | ||||
if ((typ == TYPE_A || typ == TYPE_AAAA || typ == QTYPE_ANY) && | if ((typ == TYPE_A || typ == TYPE_AAAA || typ == QTYPE_ANY) && | ||||
(cls == CLASS_IN || cls == QCLASS_ANY)) { | (cls == CLASS_IN || cls == QCLASS_ANY)) { | ||||
Show All 9 Lines | if (nquestion > 1) { | ||||
"", offset, CLASS_IN, | "", offset, CLASS_IN, | ||||
opt->datattl, &addr[n]); | opt->datattl, &addr[n]); | ||||
} else if (addr[n].v == 6) { | } else if (addr[n].v == 6) { | ||||
mustbreak = write_record_aaaa( | mustbreak = write_record_aaaa( | ||||
&outpos, outend - max_auth_size, "", offset, CLASS_IN, | &outpos, outend - max_auth_size, "", offset, CLASS_IN, | ||||
opt->datattl, &addr[n]); | opt->datattl, &addr[n]); | ||||
} | } | ||||
// printf("wrote A record: %i\n", mustbreak); | // fprintf(stdout, "wrote A record: %i\n", mustbreak); | ||||
if (mustbreak) { | if (mustbreak) { | ||||
break; | break; | ||||
} | } | ||||
n++; | n++; | ||||
outbuf[7]++; | outbuf[7]++; | ||||
} | } | ||||
} | } | ||||
// Authority section | // Authority section | ||||
if (!have_ns && outbuf[7]) { | if (!have_ns && outbuf[7]) { | ||||
int ret2 = write_record_ns(&outpos, outend, "", offset, CLASS_IN, | int ret2 = write_record_ns(&outpos, outend, "", offset, CLASS_IN, | ||||
opt->nsttl, opt->ns); | opt->nsttl, opt->ns); | ||||
// printf("wrote NS record: %i\n", ret2); | // fprintf(stdout, "wrote NS record: %i\n", ret2); | ||||
if (!ret2) { | if (!ret2) { | ||||
outbuf[9]++; | outbuf[9]++; | ||||
} | } | ||||
} else if (!outbuf[7]) { | } else if (!outbuf[7]) { | ||||
// Didn't include any answers, so reply with SOA as this is a | // Didn't include any answers, so reply with SOA as this is a | ||||
// negative response. If we replied with NS above we'd create a bad | // negative response. If we replied with NS above we'd create a bad | ||||
// horizontal referral loop, as the NS response indicates where the | // horizontal referral loop, as the NS response indicates where the | ||||
// resolver should try next. | // resolver should try next. | ||||
int ret2 = write_record_soa( | int ret2 = write_record_soa( | ||||
&outpos, outend, "", offset, CLASS_IN, opt->nsttl, opt->ns, | &outpos, outend, "", offset, CLASS_IN, opt->nsttl, opt->ns, | ||||
opt->mbox, time(NULL), 604800, 86400, 2592000, 604800); | opt->mbox, time(NULL), 604800, 86400, 2592000, 604800); | ||||
// printf("wrote SOA record: %i\n", ret2); | // fprintf(stdout, "wrote SOA record: %i\n", ret2); | ||||
if (!ret2) { | if (!ret2) { | ||||
outbuf[9]++; | outbuf[9]++; | ||||
} | } | ||||
} | } | ||||
// set AA | // set AA | ||||
outbuf[2] |= 4; | outbuf[2] |= 4; | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | int dnsserver(dns_opt_t *opt) { | ||||
msg.msg_iov = iov; | msg.msg_iov = iov; | ||||
msg.msg_iovlen = 1; | msg.msg_iovlen = 1; | ||||
msg.msg_control = &cmsg; | msg.msg_control = &cmsg; | ||||
msg.msg_controllen = sizeof(cmsg); | msg.msg_controllen = sizeof(cmsg); | ||||
for (; 1; ++(opt->nRequests)) { | for (; 1; ++(opt->nRequests)) { | ||||
ssize_t insize = recvmsg(listenSocket, &msg, 0); | ssize_t insize = recvmsg(listenSocket, &msg, 0); | ||||
// uint8_t *addr = (uint8_t*)&si_other.sin_addr.s_addr; | // uint8_t *addr = (uint8_t*)&si_other.sin_addr.s_addr; | ||||
// printf("DNS: Request %llu from %i.%i.%i.%i:%i of %i bytes\n", | // fprintf(stdout, "DNS: Request %llu from %i.%i.%i.%i:%i of %i | ||||
// (unsigned long long)(opt->nRequests), addr[0], addr[1], addr[2], | // bytes\n", (unsigned long long)(opt->nRequests), addr[0], addr[1], | ||||
// addr[3], ntohs(si_other.sin_port), (int)insize); | // addr[2], addr[3], ntohs(si_other.sin_port), (int)insize); | ||||
if (insize <= 0) continue; | if (insize <= 0) continue; | ||||
ssize_t ret = dnshandle(opt, inbuf, insize, outbuf); | ssize_t ret = dnshandle(opt, inbuf, insize, outbuf); | ||||
if (ret <= 0) continue; | if (ret <= 0) continue; | ||||
bool handled = false; | bool handled = false; | ||||
for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr; | for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr; | ||||
hdr = CMSG_NXTHDR(&msg, hdr)) { | hdr = CMSG_NXTHDR(&msg, hdr)) { | ||||
Show All 16 Lines |