aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Johnson <[email protected]>2025-11-18 23:26:07 -0500
committerSamuel Johnson <[email protected]>2025-11-18 23:26:07 -0500
commite57054801bdfe47be697f2e5a55aad2c06c0730d (patch)
tree86a803a00b5f411b58c07d4d47e25c9ca707a6e7
parent8518b3d1ac814837dbeed751112c1c9a66f86565 (diff)
Add query and question constructionfeat/query_construction
-rw-r--r--dnslite/CMakeLists.txt3
-rw-r--r--dnslite/dnslite_in.h24
-rw-r--r--dnslite/encoding.c (renamed from dnslite/dns.c)2
-rw-r--r--dnslite/encoding.h0
-rw-r--r--dnslite/message.c136
-rw-r--r--dnslite/sockets.c27
-rw-r--r--dnslite/sockets.h1
-rw-r--r--resolver/resolver.c4
-rw-r--r--tests/test_dns.c8
-rw-r--r--tests/test_dns.h1
-rw-r--r--tests/tests.c4
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)