Changeset View
Changeset View
Standalone View
Standalone View
src/seeder/dns.cpp
Show All 40 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; | ||||
// 0: ok | |||||
// -1: premature end of input, forward reference, component > 63 char, invalid | |||||
// character | |||||
// -2: insufficient space in output | |||||
static int parse_name(const uint8_t **inpos, const uint8_t *inend, | |||||
const uint8_t *inbuf, char *buf, size_t bufsize) { | |||||
size_t bufused = 0; | |||||
int init = 1; | |||||
do { | |||||
if (*inpos == inend) return -1; | |||||
// read length of next component | |||||
int octet = *((*inpos)++); | |||||
if (octet == 0) { | |||||
buf[bufused] = 0; | |||||
return 0; | |||||
} | |||||
// add dot in output | |||||
if (!init) { | |||||
if (bufused == bufsize - 1) return -2; | |||||
buf[bufused++] = '.'; | |||||
} else | |||||
init = 0; | |||||
// handle references | |||||
if ((octet & 0xC0) == 0xC0) { | |||||
if (*inpos == inend) return -1; | |||||
int ref = ((octet - 0xC0) << 8) + *((*inpos)++); | |||||
if (ref < 0 || ref >= (*inpos) - inbuf - 2) return -1; | |||||
const uint8_t *newbuf = inbuf + ref; | |||||
return parse_name(&newbuf, (*inpos) - 2, inbuf, buf + bufused, | |||||
bufsize - bufused); | |||||
} | |||||
if (octet > 63) return -1; | |||||
// copy label | |||||
while (octet) { | |||||
if (*inpos == inend) return -1; | |||||
if (bufused == bufsize - 1) return -2; | |||||
int c = *((*inpos)++); | |||||
if (c == '.') return -1; | |||||
octet--; | |||||
buf[bufused++] = c; | |||||
} | |||||
} while (1); | |||||
} | |||||
// 0: k | // 0: k | ||||
// -1: component > 63 characters | // -1: component > 63 characters | ||||
// -2: insufficent space in output | // -2: insufficent space in output | ||||
// -3: two subsequent dots | // -3: two subsequent dots | ||||
static int write_name(uint8_t **outpos, const uint8_t *outend, const char *name, | static int write_name(uint8_t **outpos, const uint8_t *outend, const char *name, | ||||
int offset) { | int offset) { | ||||
while (*name != 0) { | while (*name != 0) { | ||||
const char *dot = strchr(name, '.'); | const char *dot = strchr(name, '.'); | ||||
▲ Show 20 Lines • Show All 473 Lines • ▼ Show 20 Lines | int dnsserver(dns_opt_t *opt) { | ||||
msg.msg_namelen = sizeof(si_other); | msg.msg_namelen = sizeof(si_other); | ||||
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.sin6_addr.s6_addr; | ||||
// fprintf(stdout, "DNS: Request %llu from %i.%i.%i.%i:%i of %i | // fprintf(stdout, "DNS: Request %llu from %i.%i.%i.%i:%i of %i | ||||
// bytes\n", (unsigned long long)(opt->nRequests), addr[0], addr[1], | // bytes\n", (unsigned long long)(opt->nRequests), addr[0], addr[1], | ||||
// addr[2], addr[3], ntohs(si_other.sin_port), (int)insize); | // addr[2], addr[3], ntohs(si_other.sin6_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 |