39 while ((opt = getopt(argc, argv,
"hvV:")) != EOF) {
42 if (!strncmp(
"LOG_NULL", optarg, 8))
44 else if (!strncmp(
"LOG_NOTICE", optarg, 10))
46 else if (!strncmp(
"LOG_INFO", optarg, 8))
48 else if (!strncmp(
"LOG_ERR", optarg, 7))
50 else if (!strncmp(
"LOG_DEBUG", optarg, 9))
53 fprintf(stderr,
"Unknown log level %s\n", optarg);
58 fprintf(stderr,
"ex_dns\n");
62 fprintf(stderr,
"usage: %s [-V LOG_LEVEL]\n", argv[0]);
69static size_t build_query(
const char* name, uint16_t qtype, uint16_t
id,
unsigned char* out) {
72 out[pos++] = (
unsigned char)(
id >> 8);
73 out[pos++] = (
unsigned char)(
id & 0xFF);
85 const char* dot = strchr(p,
'.');
86 size_t llen = dot ? (size_t)(dot - p) : strlen(p);
87 out[pos++] = (
unsigned char)llen;
88 memcpy(out + pos, p, llen);
95 out[pos++] = (
unsigned char)(qtype >> 8);
96 out[pos++] = (
unsigned char)(qtype & 0xFF);
103 unsigned char q[512];
116 n_log(
LOG_ERR,
"parse id: got %u expected 0x1234", (
unsigned)
id);
119 if (strcmp(name,
"abc123.oast.example.com") != 0) {
130 if (
n_dns_parse_query(q, qlen, NULL, name,
sizeof(name), NULL) != 0 || strcmp(name,
"token.oast.test") != 0) {
137 unsigned char q[512];
138 unsigned char resp[512];
141 unsigned char ip[4] = {127, 0, 0, 1};
143 memcpy(&ipv4_be, ip, 4);
153 if ((
size_t)rlen != qlen + 16) {
154 n_log(
LOG_ERR,
"response length: got %d expected %zu", rlen, qlen + 16);
158 if ((resp[2] & 0x80) == 0) {
162 if (resp[0] != 0xBE || resp[1] != 0xEF) {
166 if (resp[6] != 0x00 || resp[7] != 0x01) {
171 if (resp[qlen] != 0xC0 || resp[qlen + 1] != 0x0C) {
172 n_log(
LOG_ERR,
"answer name is not a pointer to the question");
176 if (resp[rlen - 4] != 127 || resp[rlen - 3] != 0 || resp[rlen - 2] != 0 || resp[rlen - 1] != 1) {
184 if (
n_dns_parse_query(resp, (
size_t)rlen, NULL, name,
sizeof(name), NULL) != 0 || strcmp(name,
"tok.oast.test") != 0) {
185 n_log(
LOG_ERR,
"response question does not round-trip: '%s'", name);
192 unsigned char q[512];
193 unsigned char resp[512];
195 unsigned char ip[4] = {10, 0, 0, 1};
198 memcpy(&ipv4_be, ip, 4);
226int main(
int argc,
char** argv) {
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.