n_dns regression: parse a DNS query question and build an A-record response.
n_dns regression: parse a DNS query question and build an A-record response.
#include <stdio.h>
#include <string.h>
int opt = 0;
while ((opt = getopt(argc, argv, "hvV:")) != EOF) {
switch (opt) {
case 'V':
if (!strncmp("LOG_NULL", optarg, 8))
else if (!strncmp("LOG_NOTICE", optarg, 10))
else if (!strncmp("LOG_INFO", optarg, 8))
else if (!strncmp("LOG_ERR", optarg, 7))
else if (!strncmp("LOG_DEBUG", optarg, 9))
else {
fprintf(stderr, "Unknown log level %s\n", optarg);
exit(1);
}
break;
case 'v':
fprintf(stderr, "ex_dns\n");
exit(1);
case 'h':
default:
fprintf(stderr, "usage: %s [-V LOG_LEVEL]\n", argv[0]);
break;
}
}
}
static size_t build_query(
const char* name, uint16_t qtype, uint16_t
id,
unsigned char* out) {
size_t pos = 0;
const char* p = name;
out[pos++] = (unsigned char)(id >> 8);
out[pos++] = (unsigned char)(id & 0xFF);
out[pos++] = 0x01;
out[pos++] = 0x00;
out[pos++] = 0x00;
out[pos++] = 0x01;
out[pos++] = 0x00;
out[pos++] = 0x00;
out[pos++] = 0x00;
out[pos++] = 0x00;
out[pos++] = 0x00;
out[pos++] = 0x00;
while (*p) {
const char* dot = strchr(p, '.');
size_t llen = dot ? (size_t)(dot - p) : strlen(p);
out[pos++] = (unsigned char)llen;
memcpy(out + pos, p, llen);
pos += llen;
if (!dot)
break;
p = dot + 1;
}
out[pos++] = 0x00;
out[pos++] = (unsigned char)(qtype >> 8);
out[pos++] = (unsigned char)(qtype & 0xFF);
out[pos++] = 0x00;
out[pos++] = 0x01;
return pos;
}
unsigned char q[512];
size_t qlen;
uint16_t id = 0;
uint16_t qtype = 0;
return;
}
if (id != 0x1234) {
n_log(
LOG_ERR,
"parse id: got %u expected 0x1234", (
unsigned)
id);
}
if (strcmp(name, "abc123.oast.example.com") != 0) {
}
}
if (
n_dns_parse_query(q, qlen, NULL, name,
sizeof(name), NULL) != 0 || strcmp(name,
"token.oast.test") != 0) {
}
}
unsigned char q[512];
unsigned char resp[512];
size_t qlen;
int rlen;
unsigned char ip[4] = {127, 0, 0, 1};
uint32_t ipv4_be;
memcpy(&ipv4_be, ip, 4);
if (rlen <= 0) {
return;
}
if ((size_t)rlen != qlen + 16) {
n_log(
LOG_ERR,
"response length: got %d expected %zu", rlen, qlen + 16);
}
if ((resp[2] & 0x80) == 0) {
}
if (resp[0] != 0xBE || resp[1] != 0xEF) {
}
if (resp[6] != 0x00 || resp[7] != 0x01) {
}
if (resp[qlen] != 0xC0 || resp[qlen + 1] != 0x0C) {
n_log(
LOG_ERR,
"answer name is not a pointer to the question");
}
if (resp[rlen - 4] != 127 || resp[rlen - 3] != 0 || resp[rlen - 2] != 0 || resp[rlen - 1] != 1) {
}
{
if (
n_dns_parse_query(resp, (
size_t)rlen, NULL, name,
sizeof(name), NULL) != 0 || strcmp(name,
"tok.oast.test") != 0) {
n_log(
LOG_ERR,
"response question does not round-trip: '%s'", name);
}
}
}
unsigned char q[512];
unsigned char resp[512];
size_t qlen;
unsigned char ip[4] = {10, 0, 0, 1};
uint32_t ipv4_be;
memcpy(&ipv4_be, ip, 4);
}
}
q[12] = 0xC0;
}
}
}
int main(
int argc,
char** argv) {
return 1;
}
return 0;
}
void process_args(int argc, char **argv)
static void test_errors(void)
static size_t build_query(const char *name, uint16_t qtype, uint16_t id, unsigned char *out)
static void test_build_response(void)
static void test_parse(void)
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_DEBUG
debug-level messages
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
#define LOG_NOTICE
normal but significant condition
#define LOG_NULL
no log output
#define LOG_INFO
informational
#define N_DNS_TYPE_A
DNS resource-record type A (IPv4 address).
int n_dns_build_a_response(const unsigned char *query, size_t qlen, uint32_t ipv4_be, uint32_t ttl, unsigned char *out, size_t outsz)
Build a DNS response answering a query's first question with one A record.
#define N_DNS_QNAME_MAX
Maximum decoded QNAME length, including the terminating NUL.
int n_dns_parse_query(const unsigned char *msg, size_t len, uint16_t *id_out, char *qname_out, size_t qname_sz, uint16_t *qtype_out)
Parse the header id and the first question (QNAME + QTYPE) of a DNS message.
Common headers and low-level functions & define.
Minimal DNS message helpers: parse a query question and build an A-record response.