aboutsummaryrefslogtreecommitdiff
path: root/src/database.c
blob: a684cffdc1a171e734a4a0c9f0de710783d41a65 (plain)
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;
}