summaryrefslogtreecommitdiff
path: root/src/cache/query.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cache/query.c')
-rw-r--r--src/cache/query.c81
1 files changed, 79 insertions, 2 deletions
diff --git a/src/cache/query.c b/src/cache/query.c
index 8f5e423..7fb27c4 100644
--- a/src/cache/query.c
+++ b/src/cache/query.c
@@ -2,8 +2,9 @@
#include <stdint.h>
-#include <s6-dns/s6dns-engine.h>
+#include <s6-dns/s6dns.h>
+#include <shibari/constants.h>
#include "shibari-cache-internal.h"
static uint16_t query_delete (query *q)
@@ -12,6 +13,7 @@ static uint16_t query_delete (query *q)
QUERY(newi)->next = q->next ;
QUERY(q->next)->prev = q->prev ;
q->xindex = UINT16_MAX ;
+ q->qname.len = 0 ;
return newi ;
}
@@ -38,7 +40,82 @@ uint16_t query_succeed (uint16_t id)
return query_delete(q) ;
}
-int query_new (uint8_t source, uint16_t i, char const *ip, uint16_t port, char const *buf, uint16_t len)
+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 ;
}
+