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
|
/* ISC license. */
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <skalibs/bitarray.h>
#include <skalibs/error.h>
#include <skalibs/ip46.h>
#include <skalibs/tai.h>
#include <skalibs/random.h>
#include <skalibs/gensetdyn.h>
#include <s6-dns/s6dns-engine.h>
#include <s6-dns/s6dns-ip46.h>
#include <shibari/dcache.h>
#include "shibari-cache-internal.h"
#include <skalibs/posixishard.h>
static inline 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_event (uint16_t qid)
{
query *q = QUERY(qid) ;
dcache_string question ;
int r ;
uint32_t nodeid ;
uint16_t qtype ;
uint16_t rcode = 0 ;
switch (q->dt.status)
{
case EAGAIN :
case EWOULDBLOCK : return qid ;
case 0 : break ;
case EOPNOTSUP : rcode = 4 ; break ;
case EPROTO : rcode = 1 ; break ;
default : rcode = 2 ; break ;
}
s6dns_engine_query(&q->dt, &question.s, &question.len, &qtype) ;
r = dcache_searchnode_g(&g->dcache, &nodeid, question.s, question.len, qtype) ;
switch (r)
{
case -1 :
log_warn_unexpected_answer(question.s, question.len, qtype, 0) ;
if (!rcode) dcache_add_new_answer(&g->dcache, question.s, question.len, qtype, s6dns_engine_packet(&q->dt), s6dns_engine_packetlen(&q->dt)) ;
break ;
case 1 :
log_warn_unexpected_answer(question.s, question.len, qtype, 1) ;
if (!rcode) dcache_refresh_answer(&g->dcache, nodeid, s6dns_engine_packet(&q->dt), s6dns_engine_packetlen(&q->dt)) ;
break ;
case 0 :
{
uint16_t n = dcache_get_taskn(&g->cache, nodeid) ;
uint16_t tasks[n ? n : 1] ;
dcache_get_tasks(&g->cache, nodeid, tasks, taskn) ;
if (rcode) dcache_delete(&g->cache, nodeid) ;
else
{
dcache_add_answer(&g->dcache, nodeid, s6dns_engine_packet(&q->dt), s6dns_engine_packetlen(&q->dt)) ;
s6dns_engine_recycle(&q->dt) ;
}
for (uint16_t i = 0 ; i < n ; i++) dnstask_wakeup(tasks[i], rcode, nodeid) ;
break ;
}
}
return query_delete(q) ;
}
static inline uint16_t query_new (void)
{
uint32_t qid ;
if (!gensetdyn_new(&g->queries, &qid) || n > UINT16_MAX) dienomem() ;
query *sentinel = QUERY(g->qsentinel) ;
query *q = QUERY(qid) ;
q->prev = g->qsentinel ;
q->next = sentinel->next ;
QUERY(sentinel->next)->prev = qid ;
sentinel->next = qid ;
return qid ;
}
uint16_t query_start (uint16_t tid, char const *q, uint16_t qlen, uint16_t qtype, char const *ip4, uint16_t n4, char const *ip6, uint16_t n6, uint32_t flags)
{
query *p ;
tain qdeadline ;
uint16_t qid ;
uint16_t n = n4 + n6 ;
s6dns_ip46list_t servers = S6DNS_IP46LIST_ZERO ; /* TODO: away with all this goofiness */
{
ip46 list[n] ;
for (uint16_t i = 0 ; i < n4 ; i++) ip46_from_ip4(list + i, ip4 + (i<<2)) ;
for (uint16_t i = 0 ; i < n6 ; i++) ip46_from_ip6(list + n4 + i, ip6 + (i<<4)) ;
random_unsort(list, n, sizeof(ip46)) ;
for (uint16_t i = 0 ; i < n ; i++)
{
memcpy(servers.ip + i * SKALIBS_IP_SIZE, list[i].ip, ip46_is6(list + i) ? 16 : 4) ;
if (ip46_is6(list + i)) bitarray_set(servers.is6, i) ;
}
}
tain_add_g(&qdeadline, &g->qtto) ;
qid = query_new() ;
p = QUERY(qid) ;
if (!dcache_add_new_entry(&g->cache, q, qlen, qtype, tid)) dienomem() ;
if (!s6dns_engine_init_g(&q->dt, servers, flags, q, qlen, qtype, &qdeadline)) dienewquery() ;
return qid ;
}
|