aboutsummaryrefslogtreecommitdiff
path: root/src/database.c
blob: 491fae17321208a5de5d0d5a7222816528026e50 (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
/*
 * src/database.c
 * (c) 2021 Jonas Gunz <himself@jonasgunz.de>
 * License: MIT
 */

#include "database.h"

int database_init ( database_t* _database ) {
	unsigned int i = 0;
	size_t rr_size;

	if ( !_database )
		return 1;

	/* Initialize 2D array of tree_node pointers, paranoia style */
	if ( !( _database->zone = malloc( sizeof( tree_node_t** ) * DB_CLASS_LEN ) ) )
		return 1;

	rr_size = sizeof( struct tree_node* ) * DB_RR_LEN;
	for ( 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_destroy ( database_t* _database ) {
	unsigned int i, o;

	if ( !_database || !_database->zone )
		return 1;

	for ( i = 0; i < DB_CLASS_LEN; i++ ) {
		for ( 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 (
	database_rdata_t* _rdata,
	database_t* _database,
	const char* _qname,
	int _qname_len,
	uint16_t _qtype,
	uint16_t _qclass
) {
	uint16_t type, class;
	void* data;

	/* _qtype and _qclass start at 1, so they are invalid when 0. */

	if ( !_rdata || !_database || !_qname || !_qtype || !_qclass || _qname_len <= 0 ) {
		LOGPRINTF(_LOG_ERROR, "Invalid arguments");
		return 1;
	}

	if ( _qtype >= DB_RR_LEN || _qclass >= DB_RR_LEN ) {
		LOGPRINTF(_LOG_DEBUG, "Invalid qtype/qclass");
		return 1;
	}

	_rdata->ttl   = 0;
	_rdata->rdlen = 0;
	_rdata->rdata = NULL;

	type  = _qtype  - 1;
	class = _qclass - 1;

	data = tree_get( &_database->zone[class][type], _qname );

	if ( !data ) {
		LOGPRINTF(_LOG_DEBUG, "No matching RR found");
		return 2;
	}

	_rdata->ttl   = *( (uint32_t*) data );
	_rdata->rdlen = *( (uint16_t*)(data + 4) );
	_rdata->rdata = data + 6;

	return 0;
}