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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
/* ISC license. */
#include <stdint.h>
#include <s6-dns/s6dns.h>
#include <shibari/constants.h>
#include "shibari-cache-internal.h"
static uint16_t query_delete (query *q)
{
uint16_t newi = q->prev ;
QUERY(newi)->next = q->next ;
QUERY(q->next)->prev = q->prev ;
q->xindex = UINT16_MAX ;
q->qname.len = 0 ;
return newi ;
}
uint16_t query_abort (uint16_t id)
{
query *q = QUERY(id) ;
s6dns_engine_recycle(&q->dt) ;
return query_delete(q) ;
}
uint16_t query_fail (uint16_t id)
{
query *q = QUERY(id) ;
if (q->source == 2) tcpconnection_removequery(TCPCONNECTION(q->i), id) ;
return query_delete(q) ;
}
uint16_t query_succeed (uint16_t id)
{
query *q = QUERY(id) ;
if (q->source == 2) tcpconnection_removequery(TCPCONNECTION(q->i), id) ;
return query_delete(q) ;
}
int query_end (uint8_t source, uint16_t i, char const *ip, uint16_t port, char const *buf, uint16_t len)
{
return source < 2 ?
udpqueue_add(g->udpqueues[source] + i, source, ip, port, buf, len) :
tcpconnection_add(g->tcpconnections + i, buf, len) ;
}
int query_error (uint8_t source, uint16_t i, char const *ip, uint16_t port, s6dns_domain_t *name, uint16_t qtype, uint16_t id, unsigned int rcode)
{
s6dns_message_header_t hdr = S6DNS_MESSAGE_HEADER_ZERO ;
unsigned int pos = 12 ;
char pkt[name->len + 16] ;
hdr.id = id ;
hdr.qr = 1 ;
hdr.ra = 1 ;
hdr.rcode = rcode ;
hdr.counts.qd = 1 ;
s6dns_message_header_pack(pkt, &hdr) ;
memcpy(pkt + pos, name->s, name->len) ; pos += name->len ;
uint16_pack_big(pkt + pos, qtype) ; pos += 2 ;
uint16_pack_big(pkt + pos, SHIBARI_C_IN) ; pos += 2 ;
return query_end(source, i, ip, port, pkt, pos) ;
}
static void query_init (query *q, uint8_t source, uint16_t i, char const *ip, uint16_t port, s6dns_domain_t const *name, uint16_t qtype)
{
q->source = source ;
q->i = i ;
if (source < 2)
{
memcpy(q->ip, ip, source ? 16 : 4) ;
q->port = port ;
}
q->port = port ;
if (!stralloc_catb(&q->qname, name->s, name->len)) dienomem() ;
q->qtype = qtype ;
q->prefixlen = 0 ;
}
static query *query_new (uint8_t source, uint16_t i, char const *ip, uint16_t port, s6dns_domain_t const *name, uint16_t qtype)
{
uint16_t n = genset_new(&g->queries) ;
query *sentinel = QUERY(g->qsentinel) ;
query *q = QUERY(n) ;
query_init(q, source, i, ip, port, name, type) ;
q->prev = g->qsentinel ;
q->next = sentinel->next ;
QUERY(sentinel->next)->prev = n ;
sentinel->next = n ;
return q ;
}
int query_start (uint8_t source, uint16_t i, char const *ip, uint16_t port, char const *buf, uint16_t len)
{
dcache_key_t data ;
s6dns_message_header_t hdr ;
s6dns_message_counts_t counts ;
s6dns_domain_t name ;
unsigned int pos ;
unsigned int rcode ;
uint16_t qtype ;
if (!s6dns_message_parse_init(&hdr, &counts, buf, len, &pos)
|| !s6dns_message_parse_question(&counts, &name, &qtype, buf, len, &pos)
|| !s6dns_domain_encode(&name)) return 0 ;
if (hdr.opcode) return query_error(source, i, ip, port, &name, qtype, hdr.id, 4) ;
if (!hdr.rd) return query_error(source, i, ip, port, &name, qtype, hdr.id, 9) ;
if (cache_search(&name, qtype, &data))
return query_end(source, i, ip, port, data.s, data.len) ;
{
uint16_t j = genset_new(&g->queries) ;
query *q = QUERY(j) ;
}
return 1 ;
}
|