Changeset View
Changeset View
Standalone View
Standalone View
src/seeder/dns.cpp
Show First 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | typedef enum { | ||||
TYPE_CNAME = 5, | TYPE_CNAME = 5, | ||||
TYPE_SOA = 6, | TYPE_SOA = 6, | ||||
TYPE_MX = 15, | TYPE_MX = 15, | ||||
TYPE_AAAA = 28, | TYPE_AAAA = 28, | ||||
TYPE_SRV = 33, | TYPE_SRV = 33, | ||||
QTYPE_ANY = 255 | QTYPE_ANY = 255 | ||||
} dns_type; | } dns_type; | ||||
enum class DNSResponseCode : uint8_t { | |||||
OK = 0, | |||||
FORMAT_ERROR = 1, | |||||
SERVER_FAILURE = 2, | |||||
NAME_ERROR = 3, | |||||
NOT_IMPLEMENTED = 4, | |||||
REFUSED = 5, | |||||
}; | |||||
int parse_name(const uint8_t **inpos, const uint8_t *inend, | int parse_name(const uint8_t **inpos, const uint8_t *inend, | ||||
const uint8_t *inbuf, char *buf, size_t bufsize) { | const uint8_t *inbuf, char *buf, size_t bufsize) { | ||||
size_t bufused = 0; | size_t bufused = 0; | ||||
int init = 1; | int init = 1; | ||||
do { | do { | ||||
if (*inpos == inend) { | if (*inpos == inend) { | ||||
return -1; | return -1; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 280 Lines • ▼ Show 20 Lines | |||||
error: | error: | ||||
*outpos = oldpos; | *outpos = oldpos; | ||||
return error; | return error; | ||||
} | } | ||||
static ssize_t dnshandle(dns_opt_t *opt, const uint8_t *inbuf, size_t insize, | static ssize_t dnshandle(dns_opt_t *opt, const uint8_t *inbuf, size_t insize, | ||||
uint8_t *outbuf) { | uint8_t *outbuf) { | ||||
int error = 0; | DNSResponseCode responseCode = DNSResponseCode::OK; | ||||
if (insize < 12) { | if (insize < 12) { | ||||
// DNS header | // DNS header | ||||
return -1; | return -1; | ||||
} | } | ||||
// Predeclare various variables to avoid jumping over declarations. | // Predeclare various variables to avoid jumping over declarations. | ||||
int have_ns = 0; | int have_ns = 0; | ||||
int max_auth_size = 0; | int max_auth_size = 0; | ||||
int nquestion = 0; | int nquestion = 0; | ||||
// copy id | // copy id | ||||
outbuf[0] = inbuf[0]; | outbuf[0] = inbuf[0]; | ||||
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 response code | ||||
outbuf[3] &= ~15; | outbuf[3] &= ~15; | ||||
// check qr | // check qr | ||||
if (inbuf[2] & 128) { | if (inbuf[2] & 128) { | ||||
/* fprintf(stdout, "Got response?\n"); */ | /* fprintf(stdout, "Got response?\n"); */ | ||||
error = 1; | responseCode = DNSResponseCode::FORMAT_ERROR; | ||||
goto error; | goto error; | ||||
} | } | ||||
// check opcode | // check opcode | ||||
if (((inbuf[2] & 120) >> 3) != 0) { | if (((inbuf[2] & 120) >> 3) != 0) { | ||||
/* fprintf(stdout, "Opcode nonzero?\n"); */ | /* fprintf(stdout, "Opcode nonzero?\n"); */ | ||||
error = 4; | responseCode = DNSResponseCode::NOT_IMPLEMENTED; | ||||
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) { | ||||
/* fprintf(stdout, "No questions?\n"); */ | /* fprintf(stdout, "No questions?\n"); */ | ||||
error = 0; | responseCode = DNSResponseCode::OK; | ||||
goto error; | goto error; | ||||
} | } | ||||
if (nquestion > 1) { | if (nquestion > 1) { | ||||
/* fprintf(stdout, "Multiple questions %i?\n", nquestion); */ | /* fprintf(stdout, "Multiple questions %i?\n", nquestion); */ | ||||
error = 4; | responseCode = DNSResponseCode::NOT_IMPLEMENTED; | ||||
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]; | ||||
int offset = inpos - inbuf; | int offset = inpos - inbuf; | ||||
int ret = parse_name(&inpos, inend, inbuf, name, 256); | int ret = parse_name(&inpos, inend, inbuf, name, 256); | ||||
if (ret == -1) { | if (ret == -1) { | ||||
error = 1; | responseCode = DNSResponseCode::FORMAT_ERROR; | ||||
goto error; | goto error; | ||||
} | } | ||||
if (ret == -2) { | if (ret == -2) { | ||||
error = 5; | responseCode = DNSResponseCode::REFUSED; | ||||
goto error; | goto error; | ||||
} | } | ||||
int namel = strlen(name), hostl = strlen(opt->host); | int namel = strlen(name), hostl = strlen(opt->host); | ||||
if (strcasecmp(name, opt->host) && | if (strcasecmp(name, opt->host) && | ||||
(namel < hostl + 2 || name[namel - hostl - 1] != '.' || | (namel < hostl + 2 || name[namel - hostl - 1] != '.' || | ||||
strcasecmp(name + namel - hostl, opt->host))) { | strcasecmp(name + namel - hostl, opt->host))) { | ||||
error = 5; | responseCode = DNSResponseCode::REFUSED; | ||||
goto error; | goto error; | ||||
} | } | ||||
if (inend - inpos < 4) { | if (inend - inpos < 4) { | ||||
error = 1; | responseCode = DNSResponseCode::FORMAT_ERROR; | ||||
goto error; | goto error; | ||||
} | } | ||||
// copy question to output | // copy question to output | ||||
memcpy(outbuf + 12, inbuf + 12, inpos + 4 - (inbuf + 12)); | memcpy(outbuf + 12, inbuf + 12, inpos + 4 - (inbuf + 12)); | ||||
// set counts | // set counts | ||||
outbuf[4] = 0; | outbuf[4] = 0; | ||||
outbuf[5] = 1; | outbuf[5] = 1; | ||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | if (nquestion > 1) { | ||||
// set AA | // set AA | ||||
outbuf[2] |= 4; | outbuf[2] |= 4; | ||||
return outpos - outbuf; | return outpos - outbuf; | ||||
} | } | ||||
error: | error: | ||||
// set error | // set response code | ||||
outbuf[3] |= error & 0xF; | outbuf[3] |= uint8_t(responseCode) & 0xF; | ||||
// set counts | // set counts | ||||
outbuf[4] = 0; | outbuf[4] = 0; | ||||
outbuf[5] = 0; | outbuf[5] = 0; | ||||
outbuf[6] = 0; | outbuf[6] = 0; | ||||
outbuf[7] = 0; | outbuf[7] = 0; | ||||
outbuf[8] = 0; | outbuf[8] = 0; | ||||
outbuf[9] = 0; | outbuf[9] = 0; | ||||
outbuf[10] = 0; | outbuf[10] = 0; | ||||
▲ Show 20 Lines • Show All 91 Lines • Show Last 20 Lines |