1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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;
}
|