diff options
| author | Laurent Bercot <ska-skaware@skarnet.org> | 2026-02-06 02:16:08 +0000 |
|---|---|---|
| committer | Laurent Bercot <ska-skaware@skarnet.org> | 2026-02-06 02:16:08 +0000 |
| commit | 5ca4a0e5b65066f41af7c670e8200b0d0eba41dd (patch) | |
| tree | 76f0fdef194f6227f4903d9139157a76b18f936e /src/qmail-smtpc/smtproutes.c | |
| parent | 025de935255c05d72a5c35d86c6c5c4d212247a1 (diff) | |
| download | smtpd-starttls-proxy-5ca4a0e5b65066f41af7c670e8200b0d0eba41dd.tar.gz | |
Just name it qmail-remote after all
Diffstat (limited to 'src/qmail-smtpc/smtproutes.c')
| -rw-r--r-- | src/qmail-smtpc/smtproutes.c | 240 |
1 files changed, 0 insertions, 240 deletions
diff --git a/src/qmail-smtpc/smtproutes.c b/src/qmail-smtpc/smtproutes.c deleted file mode 100644 index d5b1fac..0000000 --- a/src/qmail-smtpc/smtproutes.c +++ /dev/null @@ -1,240 +0,0 @@ -/* ISC license. */ - -#include <skalibs/bsdsnowflake.h> - -#include <string.h> -#include <stdint.h> -#include <unistd.h> -#include <stdlib.h> -#include <errno.h> -#include <stdio.h> - -#include <skalibs/stat.h> -#include <skalibs/posixplz.h> -#include <skalibs/uint16.h> -#include <skalibs/buffer.h> -#include <skalibs/cdb.h> -#include <skalibs/cdbmake.h> -#include <skalibs/stralloc.h> -#include <skalibs/djbtime.h> -#include <skalibs/djbunix.h> - -#include <smtpd-starttls-proxy/config.h> -#include "qmailr.h" -#include "qmail-smtpc.h" - - -/* - qmail-remote uses a "constmap" for smtproutes, which is - basically a cdb in RAM. Every instance of qmail-remote - parses control/smtproutes to make the constmap. - We replace it with a real cdb, stored in the filesystem. - It saves CPU (N-1 instances of qmail-remote use the cdb - directly) and RAM (the cdb is read-only and shared). - The cdb is updated whenever control/smtproutes is newer. - We have to lock around the test to avoid several - concurrent compilations; the current lock feels too big, - the crit section can probably be made smaller, but the - behaviour is safe and avoids retry heuristics. -*/ - -/* - Key to the control/smtproutes parser - [host]:[relay[:port]] - An ip in square brackets is acceptable in host and relay, even ipv6 - - - 0 1 2 3 4 5 6 7 8 9 -st\ev EOF # \n : [ ] 0-9 a-f other special - -0 h n n n -START END COMMENT START RELAY QHOST X HOST HOST HOST X - -1 -COMMENT END COMMENT START COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT - -2 n n n -QHOST X X X QHOST X EHOST QHOST QHOST X X - -3 n h n n n -HOST X HOST X RELAY X X HOST HOST HOST X - -4 h -EHOST X X X RELAY X X X X X X - -5 ra n ra r n n n -RELAY END INRELAY START PORT QRELAY X INRELAY INRELAY INRELAY X - -6 n n n -QRELAY X X X QRELAY X ERELAY QRELAY QRELAY X X - -7 ra ra r n n n -INRELAY END X START PORT X X INRELAY INRELAY INRELAY X - -8 ra ra r -ERELAY END X START PORT X X X X X X - -9 pa pa n -PORT END X START X X X PORT X X X - -END=a, X=b - -0x0100 n push character -0x0200 h compute host length -0x0400 r compute relay length -0x0800 p compute port -0x1000 a add route entry -*/ - -static inline uint8_t cclass (char c) -{ - static uint8_t const table[128] = "0999999999299999999999999999999998918889999898786666666666399898877777788888888888888888884958898888888888888888888888888899999" ; - return c & 0x80 ? 9 : table[(uint8_t)c] - '0' ; -} - -static inline char getnext (buffer *b) -{ - char c ; - ssize_t r = buffer_get(b, &c, 1) ; - if (r == -1) qmailr_tempsys("Unable to read from control/smtproutes") ; - return r ? c : 0 ; -} - -static inline void smtproutes_compile (int fdr, int fdw) -{ - static uint16_t const table[10][10] = - { - { 0x000a, 0x0001, 0x0000, 0x0205, 0x0002, 0x000b, 0x0103, 0x0103, 0x0103, 0x000b }, - { 0x000a, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001 }, - { 0x000b, 0x000b, 0x000b, 0x0102, 0x000b, 0x0004, 0x0102, 0x0102, 0x0102, 0x000b }, - { 0x000b, 0x0103, 0x000b, 0x0205, 0x000b, 0x000b, 0x0103, 0x0103, 0x0103, 0x000b }, - { 0x000b, 0x000b, 0x000b, 0x0205, 0x000b, 0x000b, 0x000b, 0x000b, 0x000b, 0x000b }, - { 0x140a, 0x0107, 0x1400, 0x0409, 0x0006, 0x000b, 0x0107, 0x0107, 0x0107, 0x000b }, - { 0x000b, 0x000b, 0x000b, 0x0106, 0x000b, 0x0008, 0x0106, 0x0106, 0x0106, 0x000b }, - { 0x140a, 0x000b, 0x1400, 0x0409, 0x000b, 0x000b, 0x0107, 0x0107, 0x0107, 0x000b }, - { 0x140a, 0x000b, 0x1400, 0x0409, 0x000b, 0x000b, 0x000b, 0x000b, 0x000b, 0x000b }, - { 0x180a, 0x000b, 0x1800, 0x000b, 0x000b, 0x000b, 0x0109, 0x000b, 0x000b, 0x000b } - } ; - cdbmaker cm = CDBMAKER_ZERO ; - stralloc sa = STRALLOC_ZERO ; - char buf[2048] ; - buffer b = BUFFER_INIT(&buffer_read, fdr, buf, 2048) ; - uint32_t relaypos = 0, relayend = 0 ; - uint8_t state = 0 ; - if (!cdbmake_start(&cm, fdw)) qmailr_tempsys("Unable to cdbmake_start") ; - - while (state < 0x0a) - { - char c = getnext(&b) ; - uint16_t val = table[state][cclass(c)] ; - state = val & 0x000f ; - if (val & 0x0100) - { - if (!stralloc_catb(&sa, &c, 1)) qmailr_tempsys("Unable to grow stralloc") ; - } - if (val & 0x0200) - { - relaypos = sa.len + 1 ; - if (!stralloc_catb(&sa, "\0\0\31", 3)) qmailr_tempsys("Unable to grow stralloc") ; - } - if (val & 0x0400) - { - if (!stralloc_0(&sa)) qmailr_tempsys("Unable to grow stralloc") ; - relayend = sa.len ; - } - if (val & 0x0800) - { - uint16_t port ; - if (!stralloc_0(&sa)) qmailr_tempsys("Unable to grow stralloc") ; - if (!uint160_scan(sa.s + relayend, &port)) qmailr_temp("Invalid port in control/smtproutes") ; - uint16_pack_big(sa.s + relaypos, port) ; - } - if (val & 0x0100) - { - if (relaypos > 1 || relayend > 2 + relaypos) - if (!cdbmake_add(&cm, sa.s, relaypos, sa.s + relaypos, relayend - relaypos)) - qmailr_tempsys("Unable to cdbmake_add") ; - sa.len = 0 ; - } - } - if (state != 0x0a) qmailr_temp("Syntax error in control/smtproutes") ; - stralloc_free(&sa) ; - if (!cdbmake_finish(&cm)) qmailr_tempsys("Unable to cdbmake_finish") ; -} - -int smtproutes_init (smtproutes *routes) -{ - static char const *cdbfile = SMTPD_STARTTLS_PROXY_QMAIL_HOME "/run/qmail-remote/smtproutes.cdb" ; - static char const *lckfile = SMTPD_STARTTLS_PROXY_QMAIL_HOME "/run/qmail-remote/smtproutes.lock" ; - static char const *txtfile = SMTPD_STARTTLS_PROXY_QMAIL_HOME "/control/smtproutes" ; - static size_t const cdblen = sizeof(cdbfile) - 1 ; - int fdl = openc_create(lckfile) ; - if (fdl == -1) qmailr_tempsys("Unable to open run/qmail-remote/smtproutes.lock") ; - if (fd_lock(fdl, 1, 0) == -1) qmailr_tempsys("Unable to lock run/qmail-remote/smtproutes.lock") ; - - int fdc = openc_read(cdbfile) ; - if (fdc >= 0) - { - struct stat stc, str ; - if (fstat(fdc, &stc) == -1) qmailr_tempsys("Unable to fstat run/qmail-remote/smtproutes.cdb") ; - if (stat(txtfile, &str) == -1) - { - if (errno != ENOENT) qmailr_tempsys("Unable to fstat control/smtproutes") ; - unlink_void(cdbfile) ; - fd_close(fdc) ; - goto zero ; - } - if (timespec_cmp(&stc.st_mtim, &str.st_mtim) > 0) goto useit ; - fd_close(fdc) ; - } - - int fdr = openc_read(txtfile) ; - if (fdr == -1) - { - if (errno != ENOENT) qmailr_tempsys("Unable to open control/smtproutes") ; - goto zero ; - } - - { - char tmp[cdblen + 8] ; - memcpy(tmp, cdbfile, cdblen) ; - memcpy(tmp + cdblen, ":XXXXXX", 8) ; - fdc = mkstemp(tmp) ; - if (fdc == -1) qmailr_tempsys("Unable to mkstemp") ; - smtproutes_compile(fdr, fdc) ; - if (lseek(fdc, 0, SEEK_SET) == -1) qmailr_tempsys("Unable to lseek") ; - if (fsync(fdc) == -1) qmailr_tempsys("Unable to fsync run/qmail-remote/smtproutes.cdb") ; - fd_close(fdr) ; - if (rename(tmp, cdbfile) == -1) unlink_void(tmp) ; - } - - useit: - if (!cdb_init_fromfd(&routes->map, fdc)) qmailr_tempsys("Unable to mmap run/qmail-remote/smtproutes.cdb") ; - fd_close(fdc) ; - fd_close(fdl) ; - return 1 ; - - zero: - fd_close(fdl) ; - errno = 0 ; - return 0 ; -} - -int smtproutes_match (smtproutes const *routes, char const *s, stralloc *sa, size_t *pos, uint16_t *port) -{ - cdb_data data ; - int r = cdb_find(&routes->map, &data, s, strlen(s)) ; - if (r == -1) qmailr_temp("Invalid run/qmail-remote/smtproutes.cdb") ; - if (!r) return 0 ; - if (data.len < 3) return 0 ; - if (data.s[data.len - 1]) qmailr_temp("Invalid run/qmail-remote/smtproutes.cdb") ; - *pos = sa->len ; - uint16_unpack_big(data.s, port) ; - if (!stralloc_catb(sa, data.s + 2, data.len - 2)) qmailr_tempsys("Unable to grow stralloc") ; - return 1 ; -} - -void smtproutes_free (smtproutes *routes) -{ - cdb_free(&routes->map) ; -} |
