#define _DEFAULT_SOURCE #include "dat_dns.h" #include #include #include #include #include #include #include #ifdef _WIN32 #include #include #include #define test_unlink _unlink #define test_rmdir _rmdir static int test_setenv(const char *name, const char *value, int overwrite) { if (!overwrite && getenv(name)) return 0; return _putenv_s(name, value); } static int test_unsetenv(const char *name) { return _putenv_s(name, ""); } static char *test_mkdtemp(char *path) { int i; for (i = 0; i < 1000; i++) { char candidate[512]; int n = snprintf(candidate, sizeof(candidate), "%s-%ld-%d", path, (long)_getpid(), i); if (n < 0 || (size_t)n >= sizeof(candidate)) return NULL; if (_mkdir(candidate) == 0) { strcpy(path, candidate); return path; } } return NULL; } #else #include #define test_unlink unlink #define test_rmdir rmdir #define test_setenv setenv #define test_unsetenv unsetenv #define test_mkdtemp mkdtemp #endif static size_t add_txt(uint8_t *packet, size_t off, const char *text, size_t len) { packet[off++] = (uint8_t)len; memcpy(packet + off, text, len); return off + len; } int main(void) { uint8_t packet[160] = {0}; uint8_t key[32]; uint32_t ttl = 0; char value[] = "datkey=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; size_t off = 12; #ifdef _WIN32 char temporary[512] = "build/windows/dat-dns-test"; #else char temporary[] = "/tmp/dat-dns-test-XXXXXX"; #endif char old_home[1024], resolved_name[256]; uint8_t local_key[DAT_KEY_BYTES], resolved_key[DAT_KEY_BYTES]; int had_home = getenv("HOME") != NULL; size_t i; if (had_home) snprintf(old_home, sizeof(old_home), "%s", getenv("HOME")); assert(test_mkdtemp(temporary) != NULL); assert(test_setenv("HOME", temporary, 1) == 0); packet[2] = 0x81; packet[3] = 0x80; packet[5] = 1; /* one question */ packet[7] = 1; /* one answer */ packet[off++] = 7; memcpy(packet + off, "example", 7); off += 7; packet[off++] = 3; memcpy(packet + off, "com", 3); off += 3; packet[off++] = 0; packet[off++] = 0; packet[off++] = 16; /* TXT question */ packet[off++] = 0; packet[off++] = 1; /* IN */ packet[off++] = 0xc0; packet[off++] = 0x0c; packet[off++] = 0; packet[off++] = 16; /* TXT */ packet[off++] = 0; packet[off++] = 1; /* IN */ packet[off++] = 0; packet[off++] = 0; packet[off++] = 0; packet[off++] = 60; packet[off++] = 0; packet[off++] = 73; off = add_txt(packet, off, value, 20); off = add_txt(packet, off, value + 20, strlen(value) - 20); assert(off == 12 + 13 + 4 + 2 + 2 + 2 + 4 + 2 + 73); assert(dat_dns_parse_answer(packet, (unsigned)off, key, &ttl) == 0); assert(ttl == 60); assert(key[0] == 0x01 && key[1] == 0x23 && key[31] == 0xef); packet[off - 73] = 0xff; /* TXT string length exceeds the RDATA boundary */ assert(dat_dns_parse_answer(packet, (unsigned)off, key, &ttl) == -1); assert(errno == EPROTO); for (i = 0; i < sizeof(local_key); i++) local_key[i] = (uint8_t)(i * 9u + 3u); assert(dat_dns_name_set("Archive.Example.test", local_key) == 0); assert(dat_dns_name_resolve("archive.example.test", resolved_key) == 0); assert(!memcmp(local_key, resolved_key, sizeof(local_key))); assert(dat_dns_resolve("ARCHIVE.EXAMPLE.TEST", resolved_key, &ttl) == 0 && ttl == 0); assert(!memcmp(local_key, resolved_key, sizeof(local_key))); assert(dat_dns_name_for_key(local_key, resolved_name, sizeof(resolved_name)) == 0); assert(!strcmp(resolved_name, "archive.example.test")); assert(dat_dns_name_remove("archive.example.test") == 0); assert(dat_dns_name_resolve("archive.example.test", resolved_key) == -1); if (had_home) assert(test_setenv("HOME", old_home, 1) == 0); else assert(test_unsetenv("HOME") == 0); { char names[1200]; snprintf(names, sizeof(names), "%s/.dat/dat-dns", temporary); test_unlink(names); snprintf(names, sizeof(names), "%s/.dat", temporary); test_rmdir(names); } test_rmdir(temporary); return 0; }