about summary refs log tree commit diff
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 ;
 }
+