aboutsummaryrefslogtreecommitdiffstats
path: root/src/cache
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2024-07-16 01:51:04 +0000
committerLaurent Bercot <ska@appnovation.com>2024-07-16 01:51:04 +0000
commitd1c4602f80e395d1d6ab0453b8f0a6cc10aefadf (patch)
tree9e1410955b66e99d2284b0baa207d32264669716 /src/cache
parent8b435b76d68dd8f11808f0cff4d8998d2be48f4c (diff)
downloadshibari-d1c4602f80e395d1d6ab0453b8f0a6cc10aefadf.tar.gz
Refactor dcache, add prep for shibari-cache
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src/cache')
-rw-r--r--src/cache/cache.c6
-rw-r--r--src/cache/conf.c36
-rw-r--r--src/cache/dcache-internal.h18
-rw-r--r--src/cache/dcache_add.c85
-rw-r--r--src/cache/dcache_clean_expired.c20
-rw-r--r--src/cache/dcache_delete.c19
-rw-r--r--src/cache/dcache_free.c22
-rw-r--r--src/cache/dcache_init.c55
-rw-r--r--src/cache/dcache_load.c81
-rw-r--r--src/cache/dcache_save.c73
-rw-r--r--src/cache/dcache_search.c15
-rw-r--r--src/cache/deps-exe/shibari-cache8
-rw-r--r--src/cache/deps-lib/dcache8
-rw-r--r--src/cache/shibari-cache-internal.h97
-rw-r--r--src/cache/shibari-cache.c276
-rw-r--r--src/cache/tcpconnection.c49
-rw-r--r--src/cache/udpqueue.c80
17 files changed, 386 insertions, 562 deletions
diff --git a/src/cache/cache.c b/src/cache/cache.c
new file mode 100644
index 0000000..8c820fb
--- /dev/null
+++ b/src/cache/cache.c
@@ -0,0 +1,6 @@
+/* ISC license. */
+
+#include <shibari/dcache.h>
+#include "shibari-cache-internal.h"
+
+dcache_t cache = DCACHE_ZERO ;
diff --git a/src/cache/conf.c b/src/cache/conf.c
new file mode 100644
index 0000000..ea35646
--- /dev/null
+++ b/src/cache/conf.c
@@ -0,0 +1,36 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <string.h>
+
+#include <skalibs/uint32.h>
+#include <skalibs/cdb.h>
+
+#include "shibari-cache-internal.h"
+
+#include <skalibs/posixishard.h>
+
+int conf_getb (cdb const *c, char const *key, size_t keylen, cdb_data *data)
+{
+ if (keylen > 4096) return (errno = EINVAL, 0) ;
+ switch (cdb_find(c, data, key, keylen))
+ {
+ case -1 : return (errno = EILSEQ, 0) ;
+ case 0 : return (errno = ENOENT, 0) ;
+ default : return 1 ;
+ }
+}
+
+int conf_get (cdb const *c, char const *key, cdb_data *data)
+{
+ return conf_get(c, key, strlen(key), data) ;
+}
+
+int conf_get_uint32 (cdb const *c, char const *key, uint32_t *value)
+{
+ cdb_data data ;
+ if (!conf_get(conf, key, &data)) return 0 ;
+ if (data.len != 4) return (errno = EPROTO, 0) ;
+ uint32_unpack_big(data.s, value) ;
+ return 1 ;
+}
diff --git a/src/cache/dcache-internal.h b/src/cache/dcache-internal.h
deleted file mode 100644
index 2a2e36f..0000000
--- a/src/cache/dcache-internal.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* ISC license. */
-
-#ifndef SHIBARI_DCACHE_INTERNAL_H
-#define SHIBARI_DCACHE_INTERNAL_H
-
-#include <stdint.h>
-
-#include <skalibs/avlnode.h>
-#include <skalibs/gensetdyn.h>
-
-#include <shibari/dcache.h>
-
-#define DNODE(z, i) GENSETDYN_P(dcache_node_t, &(z)->storage, i)
-#define DCACHE_NODE_OVERHEAD (32 + sizeof(dcache_node_t) + 3 * sizeof(avlnode))
-
-extern void dcache_delete (dcache_t *, uint32_t) ;
-
-#endif
diff --git a/src/cache/dcache_add.c b/src/cache/dcache_add.c
deleted file mode 100644
index 7260726..0000000
--- a/src/cache/dcache_add.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* ISC license. */
-
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-
-#include <skalibs/uint64.h>
-#include <skalibs/alloc.h>
-#include <skalibs/tai.h>
-#include <skalibs/gensetdyn.h>
-#include <skalibs/avlnode.h>
-#include <skalibs/avltree.h>
-
-#include <shibari/dcache.h>
-#include "dcache-internal.h"
-
-static void uniquify (avltree const *tree, tain *stamp)
-{
- static tain const nano = { .sec = TAI_ZERO, .nano = 1 } ;
- uint32_t dummy ;
- while (avltree_search(tree, stamp, &dummy))
- tain_add(stamp, stamp, &nano) ;
-}
-
-static inline void dcache_gc_by_entry (dcache_t *z, uint64_t max)
-{
- while (z->size > max)
- {
- uint32_t oldest ;
- if (!avltree_min(&z->by_entry, &oldest)) break ;
- dcache_delete(z, oldest) ;
- }
-}
-
-static inline int dcache_add_node (dcache_t *z, dcache_node_t const *node)
-{
- uint32_t i ;
- dcache_node_t *y ;
- if (!gensetdyn_new(&z->storage, &i)) return 0 ;
- y = DNODE(z, i) ; *y = *node ;
- uniquify(&z->by_entry, &y->entry) ;
- uniquify(&z->by_expire, &y->expire) ;
- if (!avltree_insert(&z->by_key, i)) goto err1 ;
- if (!avltree_insert(&z->by_entry, i)) goto err2 ;
- if (!avltree_insert(&z->by_expire, i)) goto err3 ;
- return 1 ;
-
- err3:
- avltree_delete(&z->by_entry, &y->entry) ;
- err2:
- avltree_delete(&z->by_key, &y->key) ;
- err1:
- gensetdyn_delete(&z->storage, i) ;
- return 0 ;
-}
-
-static inline int dcache_add_unbounded (dcache_t *z, char const *key, uint16_t keylen, char const *data, uint16_t datalen, tain const *expire, tain const *stamp)
-{
- uint32_t len = (uint32_t)keylen + (uint32_t)datalen ;
- dcache_node_t y = { .key = { .s = alloc(len) } } ;
- if (!y.key.s) return 0 ;
- memcpy(y.key.s, key, keylen) ;
- memcpy(y.key.s + keylen, data, datalen) ;
- y.key.len = keylen ;
- y.datalen = datalen ;
- y.entry = *stamp ;
- y.expire = *expire ;
- if (!dcache_add_node(z, &y))
- {
- alloc_free(y.key.s) ;
- return 0 ;
- }
- z->size += DCACHE_NODE_OVERHEAD + len ;
- z->motion += DCACHE_NODE_OVERHEAD + len ;
- return 1 ;
-}
-
-int dcache_add (dcache_t *z, uint64_t max, char const *key, uint16_t keylen, char const *data, uint16_t datalen, tain const *expire, tain const *stamp)
-{
- uint64_t size = DCACHE_NODE_OVERHEAD + keylen + datalen ;
- if (size > max) return (errno = EINVAL, 0) ;
- if (z->size > max - size) dcache_clean_expired(z, stamp) ;
- if (z->size > max - size) dcache_gc_by_entry(z, max - size) ;
- return dcache_add_unbounded(z, key, keylen, data, datalen, expire, stamp) ;
-}
diff --git a/src/cache/dcache_clean_expired.c b/src/cache/dcache_clean_expired.c
deleted file mode 100644
index 0e23443..0000000
--- a/src/cache/dcache_clean_expired.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/* ISC license. */
-
-#include <stdint.h>
-
-#include <skalibs/tai.h>
-#include <skalibs/avltree.h>
-
-#include <shibari/dcache.h>
-#include "dcache-internal.h"
-
-void dcache_clean_expired (dcache_t *z, tain const *stamp)
-{
- for (;;)
- {
- uint32_t i ;
- if (!avltree_min(&z->by_expire, &i)) break ;
- if (tain_less(stamp, &DNODE(z, i)->expire)) break ;
- dcache_delete(z, i) ;
- }
-}
diff --git a/src/cache/dcache_delete.c b/src/cache/dcache_delete.c
deleted file mode 100644
index 92a5fcc..0000000
--- a/src/cache/dcache_delete.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* ISC license. */
-
-#include <skalibs/alloc.h>
-#include <skalibs/gensetdyn.h>
-#include <skalibs/avltree.h>
-
-#include <shibari/dcache.h>
-#include "dcache-internal.h"
-
-void dcache_delete (dcache_t *z, uint32_t i)
-{
- dcache_node_t *y = DNODE(z, i) ;
- avltree_delete(&z->by_expire, &y->expire) ;
- avltree_delete(&z->by_entry, &y->entry) ;
- avltree_delete(&z->by_key, &y->key) ;
- alloc_free(y->key.s) ;
- z->size -= DCACHE_NODE_OVERHEAD + y->key.len + y->datalen ;
- gensetdyn_delete(&z->storage, i) ;
-}
diff --git a/src/cache/dcache_free.c b/src/cache/dcache_free.c
deleted file mode 100644
index 16c074e..0000000
--- a/src/cache/dcache_free.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* ISC license. */
-
-#include <skalibs/alloc.h>
-#include <skalibs/gensetdyn.h>
-#include <skalibs/avltree.h>
-
-#include <shibari/dcache.h>
-
-static void dcache_node_free (void *p)
-{
- alloc_free(((dcache_node_t *)p)->key.s) ;
-}
-
-void dcache_free (dcache_t *z)
-{
- static dcache_t const dcache_zero = DCACHE_ZERO ;
- avltree_free(&z->by_expire) ;
- avltree_free(&z->by_entry) ;
- avltree_free(&z->by_key) ;
- gensetdyn_deepfree(&z->storage, &dcache_node_free) ;
- *z = dcache_zero ;
-}
diff --git a/src/cache/dcache_init.c b/src/cache/dcache_init.c
deleted file mode 100644
index d42ec62..0000000
--- a/src/cache/dcache_init.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* ISC license. */
-
-#include <stdint.h>
-#include <string.h>
-
-#include <skalibs/uint64.h>
-#include <skalibs/tai.h>
-#include <skalibs/gensetdyn.h>
-#include <skalibs/avltree.h>
-
-#include <shibari/dcache.h>
-
-static int key_cmp (void const *a, void const *b, void *x)
-{
- dcache_key_t const *ka = a ;
- dcache_key_t const *kb = b ;
- if (ka->len < kb->len) return -1 ;
- if (kb->len < ka->len) return 1 ;
- (void)x ;
- return memcmp(ka->s, kb->s, ka->len) ;
-}
-
-static int tain_cmp (void const *a, void const *b, void *x)
-{
- tain const *ta = a ;
- tain const *tb = b ;
- (void)x ;
- return tain_less(ta, tb) ? -1 : tain_less(tb, ta) ;
-}
-
-static void *key_dtok (uint32_t d, void *x)
-{
- return &GENSETDYN_P(dcache_node_t, (gensetdyn *)x, d)->key ;
-}
-
-static void *entry_dtok (uint32_t d, void *x)
-{
- return &GENSETDYN_P(dcache_node_t, (gensetdyn *)x, d)->entry ;
-}
-
-static void *expire_dtok (uint32_t d, void *x)
-{
- return &GENSETDYN_P(dcache_node_t, (gensetdyn *)x, d)->expire ;
-}
-
-
-void dcache_init (dcache_t *z, uint64_t max)
-{
- gensetdyn_init(&z->storage, sizeof(dcache_node_t), max >> 9, 3, 8) ;
- avltree_init(&z->by_key, max >> 9, 3, 8, &key_dtok, &key_cmp, &z->storage) ;
- avltree_init(&z->by_entry, max >> 9, 3, 8, &entry_dtok, &tain_cmp, &z->storage) ;
- avltree_init(&z->by_expire, max >> 9, 3, 8, &expire_dtok, &tain_cmp, &z->storage) ;
- z->size = 0 ;
- z->motion = 0 ;
-}
diff --git a/src/cache/dcache_load.c b/src/cache/dcache_load.c
deleted file mode 100644
index a0ff233..0000000
--- a/src/cache/dcache_load.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/* ISC license. */
-
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-
-#include <skalibs/posixishard.h>
-#include <skalibs/uint16.h>
-#include <skalibs/uint64.h>
-#include <skalibs/buffer.h>
-#include <skalibs/tai.h>
-#include <skalibs/djbunix.h>
-
-#include <shibari/dcache.h>
-
-static inline int dcache_load_node (dcache_t *z, uint64_t max, buffer *b)
-{
- tain entry = { .nano = 0 } ;
- tain expire = { .nano = 0 } ;
- uint16_t keylen ;
- uint16_t datalen ;
- char pack[TAI_PACK * 2 + 4] ;
- ssize_t r = buffer_get(b, pack, TAI_PACK * 2 + 4) ;
- if (!r) return 0 ;
- if (r < TAI_PACK * 2 + 4) return -1 ;
- tai_unpack(pack, tain_secp(&entry)) ;
- tai_unpack(pack + TAI_PACK, tain_secp(&expire)) ;
- uint16_unpack_big(pack + TAI_PACK * 2, &keylen) ;
- uint16_unpack_big(pack + TAI_PACK * 2 + 2, &datalen) ;
- {
- uint32_t len = (uint32_t)keylen + (uint32_t)datalen ;
- char blob[len+1] ; /* 128 kB max, it's ok */
- r = buffer_get(b, blob, len+1) ;
- if (!r) return (errno = EPIPE, -1) ;
- if (r < len) return -1 ;
- if (blob[len]) return (errno = EPROTO, -1) ;
- if (!dcache_add(z, max, blob, keylen, blob + keylen, datalen, &expire, &entry)) return -1 ;
- }
- return 1 ;
-}
-
-static inline int dcache_load_from_buffer (dcache_t *z, uint64_t max, buffer *b)
-{
- {
- char banner[sizeof(DCACHE_MAGIC) - 1] ;
- char pack[8] ;
- if (buffer_get(b, banner, sizeof(DCACHE_MAGIC) - 1) < sizeof(DCACHE_MAGIC) - 1)
- return 0 ;
- if (memcmp(banner, DCACHE_MAGIC, sizeof(DCACHE_MAGIC) - 1)) return 0 ;
- if (buffer_get(b, pack, 8) < 8) return 0 ;
- uint64_unpack_big(pack, &z->size) ;
- if (buffer_get(b, pack, 8) < 8) return 0 ;
- uint64_unpack_big(pack, &z->motion) ;
- }
- for (;;)
- {
- int r = dcache_load_node(z, max, b) ;
- if (r < 0) return 0 ;
- if (!r) break ;
- }
- return 1 ;
-}
-
-#define N 8192
-
-int dcache_load (dcache_t *z, uint64_t max, char const *file)
-{
- char buf[N] ;
- buffer b ;
- int fd = open_readb(file) ;
- if (fd == -1) return 0 ;
- buffer_init(&b, &buffer_read, fd, buf, N) ;
- if (!dcache_load_from_buffer(z, max, &b)) goto err ;
- fd_close(fd) ;
- return 1 ;
-
- err:
- dcache_free(z) ;
- fd_close(fd) ;
- return 0 ;
-}
diff --git a/src/cache/dcache_save.c b/src/cache/dcache_save.c
deleted file mode 100644
index 7277771..0000000
--- a/src/cache/dcache_save.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* ISC license. */
-
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <skalibs/posixplz.h>
-#include <skalibs/uint16.h>
-#include <skalibs/uint64.h>
-#include <skalibs/buffer.h>
-#include <skalibs/tai.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/skamisc.h>
-#include <skalibs/gensetdyn.h>
-
-#include <shibari/dcache.h>
-
-static int write_node_iter (void *data, void *aux)
-{
- dcache_node_t *y = data ;
- buffer *b = aux ;
- char pack[TAI_PACK * 2 + 4] ;
- tai_pack(pack, tain_secp(&y->entry)) ;
- tai_pack(pack + TAI_PACK, tain_secp(&y->expire)) ;
- uint16_pack(pack + TAI_PACK * 2, y->key.len) ;
- uint16_pack(pack + TAI_PACK * 2 + 2, y->datalen) ;
- if (buffer_put(b, pack, TAI_PACK * 2 + 4) == -1) return 0 ;
- if (buffer_put(b, y->key.s, y->key.len + y->datalen) == -1) return 0 ;
- if (buffer_put(b, "", 1) == -1) return 0 ;
- return 1 ;
-}
-
-static inline int dcache_save_to_buffer (dcache_t const *z, buffer *b)
-{
- char pack[16] ;
- if (buffer_puts(b, DCACHE_MAGIC) == -1) return 0 ;
- uint64_pack_big(pack, z->size) ;
- uint64_pack_big(pack + 8, z->motion) ;
- if (buffer_put(b, pack, 16) < 16) return 0 ;
-
- /* XXX: can gensetdyn_iter blow up the stack if z->storage is huge? */
- if (gensetdyn_iter_nocancel((gensetdyn *)&z->storage, gensetdyn_n(&z->storage), &write_node_iter, b) < gensetdyn_n(&z->storage)) return 0 ;
-
- return buffer_flush(b) ;
-}
-
-#define N 8192
-
-int dcache_save (dcache_t const *z, char const *file)
-{
- size_t len = strlen(file) ;
- int fd ;
- buffer b ;
- char buf[N] ;
- char tmp[len + 20] ;
- memcpy(tmp, file, len) ;
- memcpy(tmp + len, ":dcache_save:XXXXXX", 20) ;
- fd = mkstemp(tmp) ;
- if (fd == -1) return 0 ;
- buffer_init(&b, &buffer_write, fd, buf, N) ;
- if (!dcache_save_to_buffer(z, &b) || fsync(fd) < 0) goto err2 ;
- fd_close(fd) ;
- if (rename(tmp, file) == -1) goto err1 ;
- return 1 ;
-
- err2:
- fd_close(fd) ;
- err1:
- unlink_void(tmp) ;
- return 0 ;
-}
diff --git a/src/cache/dcache_search.c b/src/cache/dcache_search.c
deleted file mode 100644
index 0239b88..0000000
--- a/src/cache/dcache_search.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/* ISC license. */
-
-#include <stdint.h>
-
-#include <skalibs/avltree.h>
-
-#include <shibari/dcache.h>
-#include "dcache-internal.h"
-
-dcache_node_t *dcache_search (dcache_t *z, char const *key, uint16_t keylen)
-{
- uint32_t i ;
- dcache_key_t k = { .s = (char *)key, .len = keylen } ;
- return avltree_search(&z->by_key, &k, &i) ? DNODE(z, i) : 0 ;
-}
diff --git a/src/cache/deps-exe/shibari-cache b/src/cache/deps-exe/shibari-cache
new file mode 100644
index 0000000..841cf80
--- /dev/null
+++ b/src/cache/deps-exe/shibari-cache
@@ -0,0 +1,8 @@
+cache.o
+conf.o
+${LIBDCACHE}
+${LIBSHIBARI_COMMON}
+-ls6dns
+-lskarnet
+${SOCKET_LIB}
+${SYSCLOCK_LIB}
diff --git a/src/cache/deps-lib/dcache b/src/cache/deps-lib/dcache
deleted file mode 100644
index fcc09a0..0000000
--- a/src/cache/deps-lib/dcache
+++ /dev/null
@@ -1,8 +0,0 @@
-dcache_add.o
-dcache_clean_expired.o
-dcache_delete.o
-dcache_free.o
-dcache_init.o
-dcache_load.o
-dcache_save.o
-dcache_search.o
diff --git a/src/cache/shibari-cache-internal.h b/src/cache/shibari-cache-internal.h
new file mode 100644
index 0000000..7e03282
--- /dev/null
+++ b/src/cache/shibari-cache-internal.h
@@ -0,0 +1,97 @@
+/* ISC license. */
+
+#ifndef SHIBARI_CACHE_INTERNAL_H
+#define SHIBARI_CACHE_INTERNAL_H
+
+#include <stdint.h>
+
+#include <skalibs/cdb.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/bufalloc.h>
+#include <skalibs/genset.h>
+#include <skalibs/ip46.h>
+
+#include <s6-dns/s6dns-engine.h>
+
+#define MAXXED 1000
+
+ /* cache */
+
+extern dcache_t cache ;
+
+
+ /* conf */
+
+extern int conf_getb (cdb const *, char const *, size_t, cdb_data *) ;
+extern int conf_get (cdb const *, char const *, cdb_data *) ;
+extern int conf_get_uint32 (cdb const *, char const *, uint32_t *) ;
+
+
+ /* tcpconnection */
+
+typedef struct tcpconnection_s tcpconnection, *tcpconnection_ref ;
+struct tcpconnection_s
+{
+ bufalloc out ;
+ stralloc in ;
+ uint32_t instate ;
+} ;
+#define TCPCONNECTION_ZERO { .out = BUFALLOC_ZERO, .in = STRALLOC_ZERO, .instate = 0 }
+
+extern genset *tcpconn ; /* tcpconnection */
+#define ntcp (genset_n(tcpconn))
+
+
+ /* udpqueue */
+
+typedef struct udp4msg_s udp4msg, *udp4msg_ref ;
+struct udp4msg_s
+{
+ char ip[4] ;
+ uint16_t port ;
+ uint16_t len ;
+} ;
+#define UDP4MSG_ZERO { .ip = { 0 }, .port = 0, .len = 0 }
+
+typedef struct udp6msg_s udp6msg, *udp6msg_ref ;
+struct udp4msg_s
+{
+ char ip[16] ;
+ uint16_t port ;
+ uint16_t len ;
+} ;
+#define UDP6MSG_ZERO { .ip = { 0 }, .port = 0, .len = 0 }
+
+typedef struct udpqueue_s udpqueue, *udpqueue_ref ;
+struct udpqueue_s
+{
+ int fd ;
+ stralloc storage ;
+ genalloc messages ; /* udp[46]msg */
+} ;
+#define UDPQUEUE_ZERO { .fd = -1, .storage = STRALLOC_ZERO, .messages = GENALLOC_ZERO }
+
+extern int udpqueue_add4 (udpqueue *, char const *, uint16_t) ;
+extern int udpqueue_flush4 (udpqueue *) ;
+
+#ifdef SKALIBS_IPV6_ENABLED
+extern int udpqueue_add6 (udpqueue *, char const *, uint16_t) ;
+extern int udpqueue_flush6 (udpqueue *) ;
+#endif
+
+
+ /* main */
+
+typedef struct query_s query, *query_ref ;
+struct query_s
+{
+ s6dns_engine_t dt ;
+ size_t origin ;
+} ;
+
+extern uint32_t verbosity ;
+extern cdb confdb ;
+extern size_t n4, n6 ;
+
+#endif
diff --git a/src/cache/shibari-cache.c b/src/cache/shibari-cache.c
index 1d88556..09743d9 100644
--- a/src/cache/shibari-cache.c
+++ b/src/cache/shibari-cache.c
@@ -8,136 +8,42 @@
#include <fcntl.h>
#include <signal.h>
-#include <skalibs/ip46.h>
#include <skalibs/posixplz.h>
#include <skalibs/uint16.h>
#include <skalibs/uint32.h>
#include <skalibs/types.h>
-#include <skalibs/error.h>
#include <skalibs/strerr.h>
#include <skalibs/sgetopt.h>
-#include <skalibs/allreadwrite.h>
#include <skalibs/tai.h>
#include <skalibs/socket.h>
-#include <skalibs/ip46.h>
#include <skalibs/cdb.h>
#include <skalibs/sig.h>
#include <skalibs/iopause.h>
#include <skalibs/selfpipe.h>
+#include <skalibs/ip46.h>
+#inclide <skalibs/genalloc.h>
-#include <s6/accessrules.h>
-
+#include <shibari/config.h>
#include <shibari/common.h>
#include <shibari/cache.h>
-#define USAGE "shibari-cache [ -U ] [ -v verbosity ] [ -d notif ] [ -D cachedumpfile ] [ -w wtimeout ] [ -i rulesdir | -x rulesfile ] ip[_port]..."
-#define dieusage() strerr_dieusage(100, USAGE)
+#include "shibari-cache-internal.h"
+#define USAGE "shibari-cache [ -U ] [ -d notif ] [ -f conf.cdb ] [ -D cachedumpfile ] [ -w wtimeout ] [ -i rulesdir | -x rulesfile ]"
+#define dieusage() strerr_dieusage(100, USAGE)
-static char const *dumpfile = 0 ;
+uint32_t verbosity ;
+cdb confdb = CDB_ZERO ;
+size_t n4 = 0, n6 = 0, ntcp = 0 ;
-typedef struct shibari_ip4_s shibari_ip4 ;
-struct shibari_ip4_s
-{
- int fd ;
- char ip[4] ;
-} ;
+static int cont = 1 ;
+static int sfd = -1 ;
+static char const *dumpfile = 0 ;
-typedef struct shibari_ip6_s shibari_ip6 ;
-struct shibari_ip6_s
-{
- int fd ;
- char ip[16] ;
-} ;
-static inline void argv_pass1 (char const *const *argv, unsigned int *n4, unsigned int *n6)
+static inline void reload (void)
{
- char ip[16] ;
- for (; *argv ; argv++)
- if (ip6_scan(argv, ip))
-#ifdef SKALIBS_IPV6_ENABLED
- n6++ ;
-#else
- strerr_dief1x(100, "IPv6 listening addresses unsupported on this system") ;
-#endif
- else n4++ ;
-}
-
-static inline void argv_pass2 (char const *const *argv, shibari_ip4 *ip4, shibari_ip6 *ip6, uint16_t *ports)
-{
- unsigned int i4 = 0, i6 = 0 ;
- char ip[16] ;
- size_t len ;
- for (; *argv ; argv++)
- {
- len = ip6_scan(argv, ip) ;
- if (len)
- {
- if (argv[0][len] == '_')
- {
- uint16_t port ;
- if (!uint160_scan(*argv + len + 1))
- strerr_dief
- }
- }
- }
-}
-
-static inline void reload_cdbs (void)
-{
- cdb newtdb = CDB_ZERO ;
- if (!cdb_init(&newtdb, tdbfile))
- {
- if (verbosity) strerr_warnwu2sys("reopen DNS data file ", tdbfile) ;
- }
- else
- {
- cdb_free(&tdb) ;
- tdb = newtdb ;
- }
- if (rulestype == 2)
- {
- cdb newrules = CDB_ZERO ;
- if (!cdb_init(&newrules, rulesfile))
- {
- if (verbosity) strerr_warnwu2sys("reopen access rules file ", rulesfile) ;
- }
- else
- {
- cdb_free(&rules) ;
- rules = newrules ;
- }
- }
-}
-
-static int check_rules (ip46 const *remoteip, s6_accessrules_params_t *params, char const **loc)
-{
- s6_accessrules_result_t r ;
- params->env.len = 0 ;
- params->exec.len = 0 ;
- r = rulestype == 2 ?
- s6_accessrules_ip46_cdb(remoteip, &rules, params) :
- s6_accessrules_ip46_fs(remoteip, rulesfile, params) ;
- if (r != S6_ACCESSRULES_ALLOW) return 0 ;
-
- if (params->env.len)
- {
- char const *p ;
- if (params->env.s[params->env.len - 1])
- {
- if (verbosity)
- {
- char fmt[IP46_FMT] ;
- fmt[ip46_fmt(fmt, remoteip)] = 0 ;
- strerr_warnw6x("invalid environment parameters in rules ", rulestype == 2 ? "cdb " : "directory ", rulesfile, " for ip ", fmt, " - denying connection") ;
- }
- return 0 ;
- }
- p = memmem(params->env.s, params->env.len - 1, VAR "=", sizeof(VAR)) ;
- if (p && (p == params->env.s || !p[-1])) *loc = p + sizeof(VAR) ;
- }
- return 1 ;
}
static inline void handle_signals (void)
@@ -147,16 +53,18 @@ static inline void handle_signals (void)
case -1 : strerr_diefu1sys(111, "read selfpipe") ;
case 0 : return ;
case SIGTERM : cont = 0 ; break ;
- case SIGHUP : reload_cdbs() ; break ;
- case SIGALRM : dump_cache() ; break ;
+ case SIGHUP : reload() ; break ;
+ case SIGALRM : dump_cache(dumpfile) ; break ;
default : break ;
}
}
int main (int argc, char const *const *argv)
{
+ char const *conffile = SHIBARI_SYSCONFDIR "/shibari-cache.conf.cdb" ;
unsigned int notif = 0 ;
- unsigned int n4 = 0, n6 = 0 ;
+ char const *ip4 ;
+ char const *ip6 ;
uid_t uid = 0 ;
gid_t gid = 0 ;
PROG = "shibari-cache" ;
@@ -165,13 +73,13 @@ int main (int argc, char const *const *argv)
subgetopt l = SUBGETOPT_ZERO ;
for (;;)
{
- int opt = subgetopt_r(argc, argv, "Uv:d:D:w:i:x:", &l) ;
+ int opt = subgetopt_r(argc, argv, "Ud:f:D:w:i:x:", &l) ;
if (opt == -1) break ;
switch (opt)
{
case 'U' : flagdrop = 1 ; break ;
- case 'v' : if (!uint320_scan(l.arg, &verbosity)) dieusage() ; break ;
case 'd' : if (!uint0_scan(l.arg, &notif)) dieusage() ; break ;
+ case 'f' : conffile = l.arg ; break ;
case 'D' : dumpfile = l.arg ; break ;
case 'w' : if (!uint0_scan(l.arg, &wtimeout)) dieusage() ; break ;
case 'i' : rulesfile = l.arg ; rulestype = 1 ; break ;
@@ -180,8 +88,6 @@ int main (int argc, char const *const *argv)
}
}
argc -= l.ind ; argv += l.ind ;
- if (!argc) default_iplist ;
-
if (!ip46_scan(argv[0], &localip)) dieusage() ;
if (flagdrop)
{
@@ -203,80 +109,118 @@ int main (int argc, char const *const *argv)
close(0) ;
close(1) ;
- x[0].fd = selfpipe_init() ;
- if (x[0].fd == -1) strerr_diefu1sys(111, "create selfpipe") ;
+ sfd = selfpipe_init() ;
+ if (sfd == -1) strerr_diefu1sys(111, "create selfpipe") ;
if (!sig_altignore(SIGPIPE)) strerr_diefu1sys(111, "ignore SIGPIPE") ;
{
sigset_t set ;
sigemptyset(&set) ;
sigaddset(&set, SIGHUP) ;
sigaddset(&set, SIGTERM) ;
+ sigaddset(&set, SIGALRM) ;
if (!selfpipe_trapset(&set)) strerr_diefu1sys(111, "trap signals") ;
}
- if (!cdb_init(&tdb, tdbfile)) strerr_diefu2sys(111, "open cdb file ", tdbfile) ;
- if (rulestype == 2 && !cdb_init(&rules, rulesfile)) strerr_diefu2sys(111, "open rules file ", rulesfile) ;
-
- x[1].fd = socket_udp46_nb(ip46_is6(&localip)) ;
- if (x[1].fd == -1) strerr_diefu1sys(111, "create socket") ;
- if (socket_bind46_reuse(x[1].fd, &localip, localport) == -1) strerr_diefu1sys(111, "bind socket") ;
+ if (!cdb_init(&confdb, conffile)) strerr_diefu2sys(111, "open cdb file ", conffile) ;
- if (gid && setgid(gid) == -1) strerr_diefu1sys(111, "setgid") ;
- if (uid && setuid(uid) == -1) strerr_diefu1sys(111, "setuid") ;
- if (!tain_now_set_stopwatch_g()) strerr_diefu1sys(111, "initialize clock") ;
-
- shibari_log_start(verbosity, &localip, localport) ;
- if (notif)
{
- write(notif, "\n", 1) ;
- close(notif) ;
+ cdb_data data ;
+ if (!conf_get_uint32(&confdb, "G:logv", &verbosity))
+ strerr_diefu1sys(111, "read verbosity from config") ;
+ if (!conf_get_uint32(&confdb, "G:maxtcp", &maxtcp))
+ strerr_diefu1sys(111, "read maxtcp from config") ;
+ if (maxtcp > 4000 || maxtcp < 1)
+ strerr_dief1x(102, "invalid maxtcp in config") ;
+ if (!conf_get(&confdb, "G:listen4", &data))
+ strerr_diefu3sys(111, "read ", "G:listen4", " entry from config") ;
+ if (data.len & 3)
+ strerr_diefu2sys(102, "invalid length for ", "G:listen4") ;
+ n4 = data.len >> 2 ;
+ ip4 = data.s ;
+#ifdef SKALIBS_IPV6_ENABLED
+ if (!conf_get(&confdb, "G:listen6", &data))
+ strerr_diefu3sys(111, "read ", "G:listen6", " entry from config") ;
+ if (data.len & 15)
+ strerr_diefu2sys(102, "invalid length for ", "G:listen6") ;
+ n6 = data.len >> 4 ;
+ ip6 = data.s ;
+#endif
}
+ if (!n4 && !n6) strerr_diefu1x(102, "no listen addresses configured" ;
- while (cont)
{
- tain wstamp = TAIN_INFINITE ;
- char const *loc = 0 ;
- s6dns_message_header_t hdr ;
- s6dns_message_counts_t counts ;
- s6dns_domain_t name ;
- unsigned int rcode ;
- ssize_t r ;
- uint16_t qtype ;
- uint16_t remoteport ;
- ip46 remoteip ;
+ genalloc queries = GENALLOC_ZERO ; /* query */
+ int fd4[n4 ? n4 : 1][2] ;
+ int fd6[n6 ? n6 : 1][2] ;
+ tcpconnection tcpconn_storage[maxtcp] ;
+ uint32_t tcpconn_freelist[maxtcp] ;
+ genset tcpconn_genset ;
+ tcpconn = &tcpconn_genset ;
+ GENSET_init(tcpconn, tcpconnection, tcpconn_storage, tcpconn_freelist, maxtcp) ;
+
+ for (size_t i = 0 ; i < n4 ; i++)
+ {
+ fd4[i][0] = socket_udp4_nbcoe() ;
+ if (fd4[i][0] == -1) strerr_diefu1sys(111, "create udp4 socket") ;
+ if (socket_bind4_reuse(fd4[i][0], ip4 + (i << 2), 53) == -1)
+ {
+ char fmt[IP4_FMT] ;
+ fmt[ip4_fmt(fmt, ip4 + (i << 2))] = 0 ;
+ strerr_diefu3sys(111, "bind to ip ", fmt, " UDP port 53") ;
+ }
+ fd4[i][1] = socket_tcp4_nbcoe() ;
+ if (fd4[i][1] == -1) strerr_diefu1sys(111, "create tcp4 socket") ;
+ if (socket_bind4_reuse(fd4[i][1], ip4 + (i << 2), 53) == -1)
+ {
+ char fmt[IP4_FMT] ;
+ fmt[ip4_fmt(fmt, ip4 + (i << 2))] = 0 ;
+ strerr_diefu3sys(111, "bind to ip ", fmt, " TCP port 53") ;
+ }
+ }
+#ifdef SKALIBS_IPV6_ENABLED
+ for (size_t i = 0 ; i < n6 ; i++)
+ {
+ fd6[i][0] = socket_udp6_nbcoe() ;
+ if (fd6[i][0] == -1) strerr_diefu1sys(111, "create udp6 socket") ;
+ if (socket_bind6_reuse(fd6[i][0], ip6 + (i << 4), 53) == -1)
+ {
+ char fmt[IP6_FMT] ;
+ fmt[ip6_fmt(fmt, ip6 + (i << 4))] = 0 ;
+ strerr_diefu3sys(111, "bind to ip ", fmt, " UDP port 53") ;
+ }
+ fd6[i][1] = socket_tcp6_nbcoe() ;
+ if (fd6[i][1] == -1) strerr_diefu1sys(111, "create tcp6 socket") ;
+ if (socket_bind4_reuse(fd6[i][1], ip6 + (i << 4), 53) == -1)
+ {
+ char fmt[IP6_FMT] ;
+ fmt[ip6_fmt(fmt, ip6 + (i << 4))] = 0 ;
+ strerr_diefu3sys(111, "bind to ip ", fmt, " TCP port 53") ;
+ }
+ }
+#endif
- if (iopause_g(x, 2, &wstamp) == -1) strerr_diefu1sys(111, "iopause") ;
- if (x[0].revents & IOPAUSE_EXCEPT) strerr_dief1x(111, "trouble with selfpipe") ;
- if (x[0].revents & IOPAUSE_READ) { handle_signals() ; continue ; }
+ if (gid && setgid(gid) == -1) strerr_diefu1sys(111, "setgid") ;
+ if (uid && setuid(uid) == -1) strerr_diefu1sys(111, "setuid") ;
+ if (!tain_now_set_stopwatch_g()) strerr_diefu1sys(111, "initialize clock") ;
- r = sanitize_read(socket_recv46(x[1].fd, buf, 512, &remoteip, &remoteport, ip46_is6(&localip))) ;
- if (!r) continue ;
- if (r == -1) strerr_diefu1sys(111, "recv from socket") ;
- if (rulestype && !check_rules(&remoteip, &params, &loc)) continue ;
- if (!s6dns_message_parse_init(&hdr, &counts, buf, r, &rcode)) continue ;
- if (hdr.opcode) { rcode = 4 ; goto answer ; }
- if (!s6dns_message_parse_question(&counts, &name, &qtype, buf, r, &rcode) || !s6dns_domain_encode(&name))
+ if (notif)
{
- rcode = errno == ENOTSUP ? 4 : 1 ;
- goto answer ;
+ write(notif, "\n", 1) ;
+ close(notif) ;
}
- shibari_log_queryplus(verbosity, &name, qtype, &remoteip, remoteport) ;
- tain_wallclock_read(&wstamp) ;
- rcode = shibari_packet_tdb_answer_query(&pkt, &tdb, &hdr, &name, qtype, loc, &wstamp) ;
- answer:
- if (rcode && rcode != 3)
+ while (cont)
{
- shibari_packet_begin(&pkt, hdr.id, &name, qtype) ;
- pkt.hdr.rcode = rcode ;
- shibari_packet_end(&pkt) ;
+ size_t n = genalloc_len(query, &queries) ;
+ iopause_fd x[1 + n4 + n6 + n] ;
+ x[0].fd = sfd ;
+ x[0].events = IOPAUSE_READ ;
+ for (size_t i = 0 ; i < n4 ; i++)
+ {
+ }
}
- shibari_log_answer(verbosity, &pkt.hdr, pkt.pos) ;
- tain_add_g(&wstamp, &wtto) ;
- if (socket_sendnb46_g(x[1].fd, buf, pkt.pos, &remoteip, remoteport, &wstamp) < pkt.pos && verbosity)
- strerr_warnwu1sys("send answer") ;
- }
+ }
shibari_log_exit(verbosity, 0) ;
return 0 ;
}
diff --git a/src/cache/tcpconnection.c b/src/cache/tcpconnection.c
new file mode 100644
index 0000000..7c7f714
--- /dev/null
+++ b/src/cache/tcpconnection.c
@@ -0,0 +1,49 @@
+/* ISC license. */
+
+#include <stdint.h>
+
+#include <skalibs/cdb.h>
+
+#include "shibari-cache-internal.h"
+
+genset *tcpconn = 0 ;
+
+static inline int check (char const *key, size_t keylen)
+{
+ cdb_data data ;
+ return cdb_find(&confdb, &data, key, keylen) ;
+}
+
+int tcp4_access (char const *ip)
+{
+ int r ;
+ char key[9] = "A4:" ;
+ uint8_t i = 33 ;
+ memcpy(key+4, ip, 4) ;
+ key[8] = 0 ;
+ while (i--)
+ {
+ key[3] = i ;
+ key[4 + (i>>3)] &= ~(1U << (7 - (i & 7))) ;
+ r = check(key, 8) ;
+ if (r) return r ;
+ }
+ return 0 ;
+}
+
+int tcp6_access (char const *ip)
+{
+ int r ;
+ char key[21] = "A6:" ;
+ uint8_t i = 129 ;
+ memcpy(key+4, ip, 16) ;
+ key[20] = 0 ;
+ while (i--)
+ {
+ key[3] = i ;
+ key[4 + (i>>3)] &= ~(1U << (7 - (i & 7))) ;
+ r = check(key, 20) ;
+ if (r) return r ;
+ }
+ return 0 ;
+}
diff --git a/src/cache/udpqueue.c b/src/cache/udpqueue.c
new file mode 100644
index 0000000..022df3d
--- /dev/null
+++ b/src/cache/udpqueue.c
@@ -0,0 +1,80 @@
+/* ISC license. */
+
+#include <string.h>
+
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/socket.h>
+#include <skalibs/ip46.h>
+
+#include "shibari-cache-internal.h"
+
+int udpqueue_add4 (udpqueue *q, char const *ip, uint16_t port, char const *s, uint16_t len)
+{
+ udp4msg msg = { .port = port, .len = len } ;
+ if (!stralloc_readyplus(&q->storage, len)) return 0 ;
+ memcpy(msg.ip, ip, 4) ;
+ if (!genalloc_append(udp4msg, &q->messages, &msg)) return 0 ;
+ stralloc_catb(&q->storage, s, len) ;
+ return 1 ;
+}
+
+int udpqueue_flush4 (udpqueue *q)
+{
+ size_t n = genalloc_n(udp4msg, &q->messages) ;
+ size_t shead = 0, head = 0 ;
+ while (head < n)
+ {
+ udp4msg const *msg = genalloc_s(udp4msg, &q->messages) + head ;
+ ssize_t r = socket_send4(q->fd, q->storage.s + shead, msg->len, msg->ip, msg->port) ;
+ if (r <= 0) goto adjust ;
+ shead += msg->len ;
+ }
+ q->storage.len = 0 ;
+ genalloc_setlen(udp4msg, &q->messages, 0) ;
+ return 1 ;
+
+ adjust:
+ memmove(q->storage.s, q->storage.s + shead, q->storage.len - shead) ;
+ q->storage.len -= shead ;
+ memmove(genalloc_s(&udp4msg, &q->messages), genalloc_s(&udp4msg, &q->messages) + head, (n - head) * sizeof(udp4msg)) ;
+ genalloc_setlen(&udp4msg, &q->messages, n - head) ;
+ return 0 ;
+}
+
+#ifdef SKALIBS_IPv6_ENABLED
+
+int udpqueue_add6 (udpqueue *q, char const *ip, uint16_t port, char const *s, uint16_t len)
+{
+ udp6msg msg = { .port = port, .len = len } ;
+ if (!stralloc_readyplus(&q->storage, len)) return 0 ;
+ memcpy(msg.ip, ip, 16) ;
+ if (!genalloc_append(udp6msg, &q->messages, &msg)) return 0 ;
+ stralloc_catb(&q->storage, s, len) ;
+ return 1 ;
+}
+
+int udpqueue_flush6 (udpqueue *q)
+{
+ size_t n = genalloc_n(udp6msg, &q->messages) ;
+ size_t shead = 0, head = 0 ;
+ while (head < n)
+ {
+ udp6msg const *msg = genalloc_s(udp4msg, &q->messages) + head ;
+ ssize_t r = socket_send6(q->fd, q->storage.s + shead, msg->len, msg->ip, msg->port) ;
+ if (r <= 0) goto adjust ;
+ shead += msg->len ;
+ }
+ q->storage.len = 0 ;
+ genalloc_setlen(udp6msg, &q->messages, 0) ;
+ return 1 ;
+
+ adjust:
+ memmove(q->storage.s, q->storage.s + shead, q->storage.len - shead) ;
+ q->storage.len -= shead ;
+ memmove(genalloc_s(&udp6msg, &q->messages), genalloc_s(&udp6msg, &q->messages) + head, (n - head) * sizeof(udp6msg)) ;
+ genalloc_setlen(&udp6msg, &q->messages, n - head) ;
+ return 0 ;
+}
+
+#endif