From d1c4602f80e395d1d6ab0453b8f0a6cc10aefadf Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Tue, 16 Jul 2024 01:51:04 +0000 Subject: Refactor dcache, add prep for shibari-cache Signed-off-by: Laurent Bercot --- src/cache/shibari-cache.c | 276 ++++++++++++++++++---------------------------- 1 file changed, 110 insertions(+), 166 deletions(-) (limited to 'src/cache/shibari-cache.c') 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 #include -#include #include #include #include #include -#include #include #include -#include #include #include -#include #include #include #include #include +#include +#inclide -#include - +#include #include #include -#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) - - -static char const *dumpfile = 0 ; - +#include "shibari-cache-internal.h" -typedef struct shibari_ip4_s shibari_ip4 ; -struct shibari_ip4_s -{ - int fd ; - char ip[4] ; -} ; +#define USAGE "shibari-cache [ -U ] [ -d notif ] [ -f conf.cdb ] [ -D cachedumpfile ] [ -w wtimeout ] [ -i rulesdir | -x rulesfile ]" +#define dieusage() strerr_dieusage(100, USAGE) -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) -{ - 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++ ; -} +uint32_t verbosity ; +cdb confdb = CDB_ZERO ; +size_t n4 = 0, n6 = 0, ntcp = 0 ; -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 int cont = 1 ; +static int sfd = -1 ; +static char const *dumpfile = 0 ; -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) +static inline void reload (void) { - 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, ¬if)) 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 (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") ; + if (!cdb_init(&confdb, conffile)) strerr_diefu2sys(111, "open cdb file ", conffile) ; - 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, ¶ms, &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 ; } -- cgit v1.2.3