aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jonas Gunz <himself@jonasgunz.de> 2021-04-30 23:27:11 +0200
committerGravatar Jonas Gunz <himself@jonasgunz.de> 2021-04-30 23:27:11 +0200
commitbd8e73aad283611c096f07e0fc16aa4985f9f2eb (patch)
tree9ce9d9d41387a62dd4cc3b88669a991244d7b8b7 /src
parentba7c93085b419d1453dfb722b570245c4a725c83 (diff)
downloaddns-bd8e73aad283611c096f07e0fc16aa4985f9f2eb.tar.gz
implemented database
Diffstat (limited to 'src')
-rw-r--r--src/database.c106
-rw-r--r--src/database.h66
-rw-r--r--src/dns.h10
-rw-r--r--src/server.c28
-rw-r--r--src/server.h4
-rw-r--r--src/test.c43
-rw-r--r--src/test.h3
-rw-r--r--src/tree.c6
-rw-r--r--src/tree.h2
-rw-r--r--src/zonefile.c19
-rw-r--r--src/zonefile.h34
11 files changed, 247 insertions, 74 deletions
diff --git a/src/database.c b/src/database.c
new file mode 100644
index 0000000..a684cff
--- /dev/null
+++ b/src/database.c
@@ -0,0 +1,106 @@
+/*
+ * src/database.c
+ * (c) 2021 Jonas Gunz <himself@jonasgunz.de>
+ * License: MIT
+ */
+
+#include "database.h"
+
+static int database_init ( struct database* _database ) {
+ // Initialize 2D array of tree_node pointers, paranoia style
+ if ( !( _database->zone = malloc( sizeof( struct tree_node** ) * DB_CLASS_LEN ) ) )
+ return 1;
+
+ size_t rr_size = sizeof( struct tree_node* ) * DB_RR_LEN;
+ for ( unsigned int i = 0; i < DB_CLASS_LEN; i++ ) {
+ if ( !( _database->zone[i] = malloc( rr_size ) ) )
+ return 1;
+
+ memset( _database->zone[i], 0, rr_size );
+ }
+
+ return 0;
+}
+
+int database_populate (
+ struct database* _database,
+ char* _zonefile
+) {
+ if ( database_init( _database ) )
+ return 1;
+
+ // TODO parsing
+
+ char* qname = malloc(32);
+
+ int len = fqdn_to_qname( "test.example.com", 17, qname, 32 );
+
+ if ( len <= 0 )
+ return 1;
+
+ void* data = malloc( 10 );
+
+ *((uint32_t*)data) = 1800;
+ *((uint16_t*)(data+4)) = 4;
+ *((uint32_t*)(data+6)) = 0x45454545;
+
+ tree_insert( &_database->zone[0][0], qname, data );
+
+ return 0;
+}
+
+int database_destroy ( struct database* _database ) {
+ if ( !_database || !_database->zone )
+ return 1;
+
+ for ( unsigned int i = 0; i < DB_CLASS_LEN; i++ ) {
+ for ( unsigned int o = 0; o < DB_RR_LEN; o++ ) {
+ // TODO should we free data and key?
+ tree_destroy( &_database->zone[i][o], _TREE_FREE_DATA | _TREE_FREE_KEY );
+ }
+
+ free( _database->zone[i] );
+ }
+
+ free( _database->zone );
+ _database->zone = NULL;
+
+ return 1;
+}
+
+int database_query (
+ struct database_rdata* _rdata,
+ struct database* _database,
+ const char* _qname,
+ int _qname_len,
+ uint16_t _qtype,
+ uint16_t _qclass
+) {
+ uint16_t type, class;
+
+ // _qtype and _qclass start at 1, so they are invalid when 0.
+
+ if ( !_rdata || !_database || !_qname || !_qtype || !_qclass || _qname_len <= 0 )
+ return 1;
+
+ if ( _qtype >= DB_RR_LEN || _qclass >= DB_RR_LEN )
+ return 1;
+
+ _rdata->ttl = 0;
+ _rdata->rdlen = 0;
+ _rdata->rdata = NULL;
+
+ type = _qtype - 1;
+ class = _qclass - 1;
+
+ void* data = tree_get( &_database->zone[class][type], _qname );
+
+ if ( !data )
+ return 2;
+
+ _rdata->ttl = *( (uint32_t*) data );
+ _rdata->rdlen = *( (uint16_t*)(data + 4) );
+ _rdata->rdata = data + 6;
+
+ return 0;
+}
diff --git a/src/database.h b/src/database.h
new file mode 100644
index 0000000..e6ba882
--- /dev/null
+++ b/src/database.h
@@ -0,0 +1,66 @@
+/*
+ * src/database.h
+ * (c) 2021 Jonas Gunz <himself@jonasgunz.de>
+ * License: MIT
+ */
+
+#pragma once
+
+#include <stdlib.h>
+
+#include "tree.h"
+
+// TODO remove
+#include "dns.h"
+
+/*
+ * Structure
+ *
+ * |-CLASS_IN
+ * | |-RR_A tree
+ * | |-RR_AAAA tree
+ * | |-...
+ * |-CLASS_CS
+ * | |-...
+ * |-...
+ *
+ * !! Always substract 1 from CLASS and RR Types, they start with 1
+ *
+ * Anything other than IN is probably never needed, but easier to do now than later.
+ *
+ * Data format in tree void*
+ * 0 4 6 2+len
+ * | ttl | len | data ... |
+ * ttl: uint32_t
+ * len: uint16_t
+ *
+ */
+
+#define DB_CLASS_LEN 3
+#define DB_RR_LEN 32
+
+struct database {
+ struct tree_node*** zone;
+};
+
+struct database_rdata {
+ char* rdata;
+ uint16_t rdlen;
+ uint32_t ttl;
+};
+
+int database_populate (
+ struct database* _database,
+ char* _zonefile
+);
+
+int database_destroy ( struct database* _database );
+
+int database_query (
+ struct database_rdata* _rdata,
+ struct database* _database,
+ const char* _qname,
+ int _qname_len,
+ uint16_t _qtype,
+ uint16_t _qclass
+);
diff --git a/src/dns.h b/src/dns.h
index e8b55c2..4ee1c88 100644
--- a/src/dns.h
+++ b/src/dns.h
@@ -35,7 +35,7 @@ enum dns_record {
//Record Classes
#define CL_IN 1 //Internet
-#define CL_CS 2 //CSNET (Onsolete)
+#define CL_CS 2 //CSNET (Obsolete)
#define CL_CH 3 //CHAOS
#define CL_HS 4 //Hesiod
enum dns_record_class {
@@ -46,9 +46,9 @@ enum dns_record_class {
};
//OPCODES
-#define OP_Q 0 //Query
-#define OP_IQ 1 //Inverse Query
-#define OP_STAT 2 //Status request
+#define OP_QUERY 0 //Query
+#define OP_IQUERY 1 //Inverse Query
+#define OP_STATUS 2 //Status request
enum dns_opcode {
QUERY = 0,
INVERSE = 1,
@@ -60,7 +60,7 @@ enum dns_opcode {
#define RCODE_FORMAT 1
#define RCODE_SERVFAIL 2
#define RCODE_NAMEERR 3
-#define RCODE_NI 4 //Not implemented
+#define RCODE_NOTIMPL 4 //Not implemented
#define RCODE_REFUSED 5
enum dns_responsecode {
NOERR = 0,
diff --git a/src/server.c b/src/server.c
index 1dc65a0..26b26ca 100644
--- a/src/server.c
+++ b/src/server.c
@@ -12,6 +12,8 @@ void run_dns_server ( server_config_t* _config )
char recv_buffer[ UDP_BUFFER_LEN ];
+ struct database zone_db;
+
signal ( SIGTERM, signal_term );
signal ( SIGINT, signal_term );
@@ -21,6 +23,11 @@ void run_dns_server ( server_config_t* _config )
log_init_stdout ( _LOG_DEBUG );
+ if ( (ret = database_populate ( &zone_db, "/nofile" )) ) {
+ LOGPRINTF(_LOG_ERROR, "Failed to populate database from zonefile");
+ exit(1);
+ }
+
LOGPRINTF(_LOG_NOTE, "Initializing DNS Server on %s:%i", _config->bind_ip, _config->bind_port);
sock_server = socket ( AF_INET, SOCK_DGRAM, 0 );
@@ -73,7 +80,8 @@ void run_dns_server ( server_config_t* _config )
&sock_client_addr,
sock_client_addr_len,
recv_buffer,
- ret );
+ ret,
+ &zone_db );
}
close( sock_server );
@@ -83,7 +91,8 @@ int handle_connection ( int _socket,
struct sockaddr_in *sockaddr_client,
socklen_t sockaddr_client_len,
char* _buffer,
- int _bufflen )
+ int _bufflen,
+ struct database* _zone_db )
{
struct dns_message msg;
@@ -98,12 +107,21 @@ int handle_connection ( int _socket,
LOGPRINTF(_LOG_DEBUG, "Request for %s QTYPE %i", out, msg.question[0].qtype);
}
- //Always return NXDOMAIN
+ // Only handles first request
+ // TODO heavy refactoring. major POC vibe
+ struct database_rdata rdata;
struct dns_question* quest = & msg.question[0];
- struct dns_header head = {msg.header.id,1,OP_Q,0,0,0,0,0,RCODE_NOERR,0,1,0,0};
- struct dns_answer answ = {quest->qname, quest->qname_len, RR_A, CL_IN, 69, 4, "aaa" };
+ int db_ret = database_query( &rdata, _zone_db, quest->qname, quest->qname_len, quest->qtype, quest->qclass );
+ if (db_ret) {
+
+ LOGPRINTF(_LOG_DEBUG, "DB Query exited with code %i", db_ret);
+ return 1;
+ }
+
+ struct dns_header head = {msg.header.id,1,OP_QUERY,0,0,0,0,0,RCODE_NOERR,0,1,0,0};
+ struct dns_answer answ = {quest->qname, quest->qname_len, RR_A, CL_IN, rdata.ttl, rdata.rdlen, rdata.rdata };
char ret[512];
int hlen = dns_construct_header ( ret, 512, &head );
diff --git a/src/server.h b/src/server.h
index d59eba6..7f74088 100644
--- a/src/server.h
+++ b/src/server.h
@@ -22,6 +22,7 @@
#include "dns.h"
#include "log.h"
+#include "database.h"
#define UDP_BUFFER_LEN 512
@@ -38,6 +39,7 @@ int handle_connection ( int _socket,
struct sockaddr_in *sockaddr_client,
socklen_t sockaddr_client_len,
char* _buffer,
- int _bufflen );
+ int _bufflen,
+ struct database* _zone_db );
void signal_term ( );
diff --git a/src/test.c b/src/test.c
index 41dd197..a74edcf 100644
--- a/src/test.c
+++ b/src/test.c
@@ -12,12 +12,22 @@ void run_test ()
log_init_stdout(_LOG_DEBUG);
//Space for temporary tests
+ test_database();
+
+ return;
//tree_balanced_insert(NULL, NULL, NULL, 15 );
+ //
//Normal tests
- test_tree();
- //test_dns_parsing();
- test_dns_message_fuzz();
- test_dns_qname_fuzz();
+
+ int ret = 0;
+
+ ret += test_tree();
+ ret += test_dns_parsing();
+ ret += test_dns_message_fuzz();
+ ret += test_dns_qname_fuzz();
+ ret += test_database();
+
+ exit(ret);
}
int test_tree ()
@@ -47,11 +57,11 @@ int test_tree ()
printf("len_cnt %i\n", len_cnt);
- tree_balanced_insert( &root, data, keys, len );
+ tree_balanced_insert( &root, (void**)data, keys, len );
printf("After Insert\n");
- printf("%s\n", tree_get(&root, "aa"));
+ printf("%s\n", (char*)tree_get(&root, "aa"));
for ( int i = 0; i < len; i++ ) {
if ( strcmp( tree_get(&root, keys[i]), data[i] ) )
@@ -160,4 +170,25 @@ int test_dns_message_fuzz()
return 0;
}
+
+int test_database(){
+ struct database db;
+ struct database_rdata rdata;
+
+ if ( database_populate( &db, "nofile" ) )
+ return 1;
+
+ printf("Populated\n");
+
+ char* qname = malloc(32);
+ int len = fqdn_to_qname( "test.example.com.", 18, qname, 32 );
+
+ int ret = database_query ( &rdata, &db, qname, len, 1, 1 );
+ printf("Return code %i, rdlen %i\n", ret, rdata.rdlen);
+
+ database_destroy( &db );
+
+ return 0;
+}
+
#endif
diff --git a/src/test.h b/src/test.h
index ea3543d..989fecf 100644
--- a/src/test.h
+++ b/src/test.h
@@ -8,6 +8,7 @@
#include <stdio.h>
#include "tree.h"
#include "dns.h"
+#include "database.h"
/*
* TODO
@@ -28,4 +29,6 @@ int test_dns_qname_fuzz();
int test_dns_message_fuzz();
+int test_database();
+
#endif
diff --git a/src/tree.c b/src/tree.c
index 4395c81..974a5bb 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -6,7 +6,7 @@
#include "tree.h"
-static int string_compare ( char* _1, char* _2 );
+static int string_compare ( const char* _1, const char* _2 );
/**
* ignore-case alphabetical string compare
@@ -15,7 +15,7 @@ static int string_compare ( char* _1, char* _2 );
* -1 :: _1 < _2
* +1 :: _1 > _2
* */
-static int string_compare ( char* _1, char* _2 )
+static int string_compare ( const char* _1, const char* _2 )
{
if ( !_1 || !_2 )
return 99;
@@ -144,7 +144,7 @@ int tree_destroy ( struct tree_node** _root, uint8_t _options )
return 0;
}
-void* tree_get ( struct tree_node** _root, char* _query )
+void* tree_get ( struct tree_node** _root, const char* _query )
{
struct tree_node** node = _root;
diff --git a/src/tree.h b/src/tree.h
index 2b69301..2623cb3 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -72,6 +72,6 @@ int tree_balanced_insert ( struct tree_node** _root, void* _data[], char* _key[
/**
* Returns (void*)node->data on success, NULL on failure
* */
-void* tree_get ( struct tree_node** _root, char* _query );
+void* tree_get ( struct tree_node** _root, const char* _query );
int tree_destroy( struct tree_node** _root, uint8_t _options );
diff --git a/src/zonefile.c b/src/zonefile.c
deleted file mode 100644
index 7ef3535..0000000
--- a/src/zonefile.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * zonefile.c
- * (c) 2019 Jonas Gunz
- * License: MIT
- * */
-
-#include "zonefile.h"
-
-int zonefile_parse ( char* _filename, struct record_node* _dns_zone )
-{
- return 1;
-}
-
-int zonefile_query ( char* _hostname, struct record_entry* _entry )
-{
- return 1;
-}
-
-
diff --git a/src/zonefile.h b/src/zonefile.h
deleted file mode 100644
index 633e824..0000000
--- a/src/zonefile.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * zonefile.h
- * (c) 2019 Jonas Gunz
- * License: MIT
- * */
-
-#pragma once
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "tree.h"
-
-struct record_entry {
- char* name;
- uint32_t ttl;
- uint16_t class;
- uint16_t type;
- uint16_t rdlength;
- char* rd;
-};
-
-struct record_node {
- struct record_entry* rr;
- struct record_node* below;
- struct record_node* above;
-};
-
-/**
- * */
-int zonefile_parse ( char* _filename, struct record_node* _dns_zone );
-
-int zonefile_query ( char* _hostname, struct record_entry* _entry );
-