Changeset View
Changeset View
Standalone View
Standalone View
src/seeder/dns.h
#ifndef BITCOIN_SEEDER_DNS_H | #ifndef BITCOIN_SEEDER_DNS_H | ||||
#define BITCOIN_SEEDER_DNS_H 1 | #define BITCOIN_SEEDER_DNS_H 1 | ||||
#include <cstdint> | #include <cstdint> | ||||
#include <cstdio> | |||||
#include <cstring> | |||||
struct addr_t { | struct addr_t { | ||||
int v; | int v; | ||||
union { | union { | ||||
uint8_t v4[4]; | uint8_t v4[4]; | ||||
uint8_t v6[16]; | uint8_t v6[16]; | ||||
} data; | } data; | ||||
}; | }; | ||||
struct dns_opt_t { | struct dns_opt_t { | ||||
int port; | int port; | ||||
int datattl; | int datattl; | ||||
int nsttl; | int nsttl; | ||||
const char *host; | const char *host; | ||||
const char *ns; | const char *ns; | ||||
const char *mbox; | const char *mbox; | ||||
uint32_t (*cb)(void *opt, char *requested_hostname, addr_t *addr, | uint32_t (*cb)(void *opt, char *requested_hostname, addr_t *addr, | ||||
uint32_t max, uint32_t ipv4, uint32_t ipv6); | uint32_t max, uint32_t ipv4, uint32_t ipv6); | ||||
// stats | // stats | ||||
uint64_t nRequests; | uint64_t nRequests; | ||||
}; | }; | ||||
// 0: ok | |||||
// -1: premature end of input, forward reference, component > 63 char, invalid | |||||
// character | |||||
// -2: insufficient space in output | |||||
static inline 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); | |||||
} | |||||
int dnsserver(dns_opt_t *opt); | int dnsserver(dns_opt_t *opt); | ||||
#endif // BITCOIN_SEEDER_DNS_H | #endif // BITCOIN_SEEDER_DNS_H |