diff options
| -rw-r--r-- | dnslite/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | dnslite/dnslite_in.h | 24 | ||||
| -rw-r--r-- | dnslite/encoding.c (renamed from dnslite/dns.c) | 2 | ||||
| -rw-r--r-- | dnslite/encoding.h | 0 | ||||
| -rw-r--r-- | dnslite/message.c | 136 | ||||
| -rw-r--r-- | dnslite/sockets.c | 27 | ||||
| -rw-r--r-- | dnslite/sockets.h | 1 | ||||
| -rw-r--r-- | resolver/resolver.c | 4 | ||||
| -rw-r--r-- | tests/test_dns.c | 8 | ||||
| -rw-r--r-- | tests/test_dns.h | 1 | ||||
| -rw-r--r-- | tests/tests.c | 4 |
11 files changed, 191 insertions, 19 deletions
diff --git a/dnslite/CMakeLists.txt b/dnslite/CMakeLists.txt index 7e53d6f..584c3ba 100644 --- a/dnslite/CMakeLists.txt +++ b/dnslite/CMakeLists.txt @@ -6,7 +6,8 @@ set(dnslite_api_headers ) set(dnslite_c_sources - dns.c + encoding.c + message.c sockets.c ) diff --git a/dnslite/dnslite_in.h b/dnslite/dnslite_in.h index a399b8b..c2a7b20 100644 --- a/dnslite/dnslite_in.h +++ b/dnslite/dnslite_in.h @@ -1,8 +1,7 @@ /** * \file dnslite_in.h * \brief This file contains the API for dnslite. - * \copyright Copyright 2025 Samuel Johnson. All rights reserved. - * \license This project is released under the 3-Clause BSD License. + * \copyright Copyright 2025 Samuel Johnson. All rights reserved. This project is released under the 3-Clause BSD License. */ #ifndef DNSLITE_API_H #define DNSLITE_API_H @@ -11,12 +10,18 @@ #include <stdbool.h> #include <stdint.h> +#include <stdio.h> #define DNSLITE_VERSION_MAJOR @dnslite_VERSION_MAJOR@ #define DNSLITE_VERSION_MINOR @dnslite_VERSION_MINOR@ #define DNSLITE_VERSION_PATCH @dnslite_VERSION_PATCH@ #define DNSLITE_VERSION_STRING "@dnslite_VERSION@" +#define INITIAL_QUESTIONS_CAPACITY 2 +#define INITIAL_ANSWERS_CAPACITY 1 +#define INITIAL_NAMESERVERS_CAPACITY 1 +#define INITIAL_ADDITIONALS_CAPACITY 1 + /** * \defgroup DnslTypes Data Types * \brief All required types for the use of the API functions @@ -129,7 +134,7 @@ enum dnsl_rrecord_class { */ /** - * Initializes socket library. + * Initializes library. * * Behavior is platform specific: * - Windows: WSAStartup @@ -138,10 +143,10 @@ enum dnsl_rrecord_class { * @param error \ref DNSL_ERROR_SOCKET_FAILED. * @return Zero or platform-specific error code. */ -DNSLITE_EXPORT int dnsl_socket_init (struct dnsl_error *error); +DNSLITE_EXPORT int dnsl_init (struct dnsl_error *error); /** - * Terminates socket library. + * Terminates library. * * Behavior is platform specific: * - Windows: WSACleanup @@ -149,7 +154,7 @@ DNSLITE_EXPORT int dnsl_socket_init (struct dnsl_error *error); * * @returns Zero or a platform-specific error code. */ -DNSLITE_EXPORT int dnsl_socket_fini (void); +DNSLITE_EXPORT int dnsl_fini (void); /** * Encodes hostname in fashion required by RFC 1035. @@ -229,6 +234,13 @@ DNSLITE_EXPORT void dnsl_append_question (dnsl_msg_ref msg, dnsl_question_ref qu DNSLITE_EXPORT void dnsl_append_rrecord (dnsl_msg_ref msg, dnsl_rrecord_ref rrecord); /** + * Prints out the content of the DNS query to a stream. + * + * @param msg The DNS query. + */ +DNSLITE_EXPORT void dnsl_msg_format_pretty (FILE *stream, dnsl_msg_ref msg); + +/** * Frees a DNS message. * * Frees both the header for the message and all the resources diff --git a/dnslite/dns.c b/dnslite/encoding.c index c752f1c..b9994de 100644 --- a/dnslite/dns.c +++ b/dnslite/encoding.c @@ -4,7 +4,7 @@ #include <stdlib.h> #include <string.h> -const char *dnsl_encode_hostname (const char *hostname, struct dnsl_error *error) +dnsl_hostname_ref dnsl_encode_hostname (const char *hostname, struct dnsl_error *error) { size_t len = strlen(hostname); if (len > 253) diff --git a/dnslite/encoding.h b/dnslite/encoding.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/dnslite/encoding.h diff --git a/dnslite/message.c b/dnslite/message.c new file mode 100644 index 0000000..438064d --- /dev/null +++ b/dnslite/message.c @@ -0,0 +1,136 @@ +#include "dnslite.h" + +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> + +struct dnsl_question { + dnsl_hostname_ref hostname; + enum dnsl_question_type type; + enum dnsl_question_class class; +}; + +struct dnsl_rrecord { + dnsl_hostname_ref hostname; + enum dnsl_rrecord_type type; + enum dnsl_rrecord_class class; + uint32_t ttl; + + uint16_t data_length; + const char *data; +}; + +struct dnsl_msg { + uint16_t id; + bool is_query; + enum dnsl_msg_opcode opcode; + bool is_authoritative; + bool is_truncated; + bool should_recurse; + enum dnsl_msg_response_type response_code; + + uint16_t questions_cap; + uint16_t questions_count; + + uint16_t answers_cap; + uint16_t answers_count; + + uint16_t namesevers_cap; + uint16_t nameservers_count; + + uint16_t additionals_cap; + uint16_t additionals_count; + + dnsl_question_ref *questions; + dnsl_rrecord_ref *answers; + dnsl_rrecord_ref *nameservers; + dnsl_rrecord_ref *additionals; +}; + +dnsl_msg_ref dnsl_new_query (enum dnsl_msg_opcode opcode, bool recursion_desired) { + dnsl_msg_ref query = (dnsl_msg_ref) malloc(sizeof *query); + + query->id = rand() & 0x0000ffff; + query->is_query = true; + query->opcode = opcode; + query->is_authoritative = false; + query->is_truncated = false; + query->should_recurse = recursion_desired; + query->response_code = DNSL_RESPONSE_TYPE_NONE; + + // TODO: add memory allocation fail checks here + + query->questions_cap = INITIAL_QUESTIONS_CAPACITY; + query->questions_count = 0; + query->questions = malloc(sizeof *query->questions * INITIAL_QUESTIONS_CAPACITY); + + query->answers_cap = INITIAL_ANSWERS_CAPACITY; + query->answers_count = 0; + query->answers = malloc(sizeof *query->answers * INITIAL_ANSWERS_CAPACITY); + + query->namesevers_cap = INITIAL_NAMESERVERS_CAPACITY; + query->nameservers_count = 0; + query->nameservers = malloc(sizeof *query->nameservers * INITIAL_NAMESERVERS_CAPACITY); + + query->additionals_cap = INITIAL_ADDITIONALS_CAPACITY; + query->additionals_count = 0; + query->additionals = malloc(sizeof *query->additionals * INITIAL_ADDITIONALS_CAPACITY); + + return query; +} + +dnsl_question_ref dnsl_new_question ( + dnsl_hostname_ref hostname, + enum dnsl_question_type type, + enum dnsl_question_class class, + struct dnsl_error *error) { + (void) error; + + dnsl_question_ref question = (dnsl_question_ref) malloc(sizeof *question); + + question->hostname = hostname; + question->type = type; + question->class = class; + + hostname = NULL; + + return question; +} + +void dnsl_append_question (dnsl_msg_ref msg, dnsl_question_ref question) { + if (msg->questions_count >= msg->questions_cap) { + msg->questions = realloc(msg->questions, sizeof *msg->questions * 2); + } + + msg->questions[msg->questions_count] = question; + question = NULL; +} + +void free_question (dnsl_question_ref question) { + free((char *) question->hostname); + free(question); +} + +void free_rrecord (dnsl_rrecord_ref rrecord) { + free((char *) rrecord->hostname); + free((char *) rrecord->data); + free(rrecord); +} + +void dnsl_free_msg (dnsl_msg_ref msg) { + for (int i = 0; i < msg->questions_count; i++) { + free_question(msg->questions[i]); + } + + for (int i = 0; i < msg->answers_count; i++) { + free_rrecord(msg->answers[i]); + } + + for (int i = 0; i < msg->nameservers_count; i++) { + free_rrecord(msg->nameservers[i]); + } + + for (int i = 0; i < msg->additionals_count; i++) { + free_rrecord(msg->additionals[i]); + } +} diff --git a/dnslite/sockets.c b/dnslite/sockets.c index d7cb883..ddc5c92 100644 --- a/dnslite/sockets.c +++ b/dnslite/sockets.c @@ -1,9 +1,25 @@ #include "dnslite.h" #include "sockets.h" +#include <stdlib.h> #include <string.h> +#include <time.h> -int dnsl_socket_init (struct dnsl_error *error) +unsigned long jenkins_96_mix (unsigned long a, unsigned long b, unsigned long c) { + a = a - b; a = a - c; a = a ^ (c >> 13); + b = b - c; b = b - a; b = b ^ (a << 8); + c = c - a; c = c - b; c = c ^ (b >> 13); + a = a - b; a = a - c; a = a ^ (c >> 12); + b = b - c; b = b - a; b = b ^ (a << 16); + c = c - a; c = c - b; c = c ^ (b >> 5); + a = a - b; a = a - c; a = a ^ (c >> 3); + b = b - c; b = b - a; b = b ^ (a << 10); + c = c - a; c = c - b; c = c ^ (b >> 15); + + return c; +} + +int dnsl_init (struct dnsl_error *error) { #ifdef _WIN32 WSADATA wsaData; @@ -30,15 +46,16 @@ int dnsl_socket_init (struct dnsl_error *error) return wsaData.wVersion; } - - return 0; + + srand(jenkins_96_mix(clock(), time(NULL), GetCurrentProcessId())); #else (void) error; - return 0; + srand(jenkins_96_mix(clock(), time(NULL), getpid())); #endif + return 0; } -int dnsl_socket_fini (void) +int dnsl_fini (void) { #ifdef _WIN32 return WSACleanup(); diff --git a/dnslite/sockets.h b/dnslite/sockets.h index e47976c..5ae9c2c 100644 --- a/dnslite/sockets.h +++ b/dnslite/sockets.h @@ -8,6 +8,7 @@ #elif defined(__linux__) +#include <unistd.h> #include <sys/socket.h> #define SOCKET int #define SOCKET_IS_VALID(socket) ((socket) >= 0) diff --git a/resolver/resolver.c b/resolver/resolver.c index 0456192..044833c 100644 --- a/resolver/resolver.c +++ b/resolver/resolver.c @@ -5,12 +5,12 @@ int main (void) { struct dnsl_error error; - if(dnsl_socket_init(&error) != 0) + if(dnsl_init(&error) != 0) { printf("Could not initialize sockets: [%d] %s\n", error.code, error.msg); return 1; } - dnsl_socket_fini(); + dnsl_fini(); return 0; } diff --git a/tests/test_dns.c b/tests/test_dns.c index 1b15e1c..29ed05e 100644 --- a/tests/test_dns.c +++ b/tests/test_dns.c @@ -1,8 +1,12 @@ #include "dnslite.h" #include "unity.h" -void test_dnsl_encode_hostname (void) -{ +void test_dnsl_encode_hostname (void) { struct dnsl_error error; TEST_ASSERT_EQUAL_STRING_LEN("\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x03\x63\x6f\x6d\x00", dnsl_encode_hostname("dns.google.com", &error), 16); } + +void test_dnsl_construct_question_query (void) { + struct dnsl_error error; + dnsl_encode_hostname("git.paterissa.net", &error); +} diff --git a/tests/test_dns.h b/tests/test_dns.h index d481edf..cf6d961 100644 --- a/tests/test_dns.h +++ b/tests/test_dns.h @@ -2,5 +2,6 @@ #define DNSL_TESTS_DNS_H void test_dnsl_encode_hostname (void); +void test_dnsl_construct_question_query (void); #endif diff --git a/tests/tests.c b/tests/tests.c index 9ec1a84..d871f1d 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -7,7 +7,7 @@ void setUp (void) { struct dnsl_error error; - if(dnsl_socket_init(&error) != 0) + if(dnsl_init(&error) != 0) { printf("Could not initialize sockets: [%d] %s\n", error.code, error.msg); } @@ -15,7 +15,7 @@ void setUp (void) void tearDown (void) { - dnsl_socket_fini(); + dnsl_fini(); } int main (void) |
