aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmail-smtpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmail-smtpc')
-rw-r--r--src/qmail-smtpc/deps-exe/qmail-smtpc6
-rw-r--r--src/qmail-smtpc/deps-lib/qmailr6
-rw-r--r--src/qmail-smtpc/dns.c315
-rw-r--r--src/qmail-smtpc/qmail-smtpc.c86
-rw-r--r--src/qmail-smtpc/qmail-smtpc.h46
-rw-r--r--src/qmail-smtpc/qmailr.h66
-rw-r--r--src/qmail-smtpc/qmailr_control.c82
-rw-r--r--src/qmail-smtpc/qmailr_error.c38
-rw-r--r--src/qmail-smtpc/qmailr_tcpto.c157
-rw-r--r--src/qmail-smtpc/qmailr_tls.c47
-rw-r--r--src/qmail-smtpc/qmailr_utils.c60
-rw-r--r--src/qmail-smtpc/smtproutes.c240
12 files changed, 0 insertions, 1149 deletions
diff --git a/src/qmail-smtpc/deps-exe/qmail-smtpc b/src/qmail-smtpc/deps-exe/qmail-smtpc
deleted file mode 100644
index 4484f9b..0000000
--- a/src/qmail-smtpc/deps-exe/qmail-smtpc
+++ /dev/null
@@ -1,6 +0,0 @@
-dns.o
-smtproutes.o
-libqmailr.a.xyzzy
--lskadns
--ls6dns
--lskarnet
diff --git a/src/qmail-smtpc/deps-lib/qmailr b/src/qmail-smtpc/deps-lib/qmailr
deleted file mode 100644
index c1095ed..0000000
--- a/src/qmail-smtpc/deps-lib/qmailr
+++ /dev/null
@@ -1,6 +0,0 @@
-qmailr_control.o
-qmailr_error.o
-qmailr_tcpto.o
-qmailr_tls.o
-qmailr_utils.o
--lskarnet
diff --git a/src/qmail-smtpc/dns.c b/src/qmail-smtpc/dns.c
deleted file mode 100644
index 90aade4..0000000
--- a/src/qmail-smtpc/dns.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/* ISC license. */
-
-#include <string.h>
-#include <stdint.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include <skalibs/tai.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/genalloc.h>
-#include <skalibs/iopause.h>
-#include <skalibs/ip46.h>
-#include <skalibs/random.h>
-
-#include <s6-dns/s6dns.h>
-#include <s6-dns/skadns.h>
-
-#include "qmailr.h"
-#include "qmail-smtpc.h"
-
-typedef struct cnameinfo_s cnameinfo, *cnameinfo_ref ;
-struct cnameinfo_s
-{
- stralloc sa ;
- size_t atpos ;
- uint16_t id ;
- uint16_t count ;
-} ;
-
-typedef struct mxipinfo_s mxipinfo, mxipinfo_ref ;
-struct mxipinfo_s
-{
- stralloc ip4 ;
- stralloc ip6 ;
- uint16_t id4 ;
- uint16_t id6 ;
-} ;
-#define MXIPINFO_ZERO { .ip4 = STRALLOC_ZERO, .ip6 = STRALLOC_ZERO, .id4 = UINT16_MAX, .id6 = UINT16_MAX }
-
-static int mx_cmp (void const *a, void const *b)
-{
- s6dns_message_rr_mx_t const *aa = a ;
- s6dns_message_rr_mx_t const *bb = b ;
- return aa->preference < bb-> preference ? -1 : aa->preference > bb->preference ;
-}
-
-static unsigned int use_host_as_mx (skadns_t *a, char const *host, genalloc *mxip, tain const *deadline)
-{
- unsigned int newreqs = 0 ;
- mxipinfo info = MXIPINFO_ZERO ;
- s6dns_domain_t q ;
- if (!s6dns_domain_fromstring_noqualify_encode(&q, host, strlen(host)))
- qmailr_tempsys("Unable to DNS-encode host domain") ;
- if (!skadns_send_g(a, &info.id4, &q, S6DNS_T_A, deadline, deadline))
- qmailr_tempsys("Unable to send A DNS query") ;
- newreqs++ ;
-#ifdef SKALIBS_IPV6_ENABLED
- if (!skadns_send_g(a, &info.id6, &q, S6DNS_T_AAAA, deadline, deadline))
- qmailr_tempsys("Unable to send AAAA DNS query") ;
- newreqs++ ;
-#endif
- if (!genalloc_catb(mxipinfo, mxip, &info, 1)) dienomem() ;
- return newreqs ;
-}
-
- /*
- The point of this monster here is to do all the DNS resolutions in parallel,
- to avoid compounding network latency. One of the many things that could never
- be done by patching qmail-remote.
- 1 sender + n-1 recipients are given in eaddr.
- - loop around CNAME until we get the canonical name, for the n eaddrs
- - either lookup the MX for the host then find all the A and AAAAs of all the MXes,
- or get the A and AAAAs of the host directly (if smtproutes)
- - do not keep the As and AAAAs listed in ipme
- - sort the set of IPs by MX preference
- When done, quote all the boxnames in eaddr.
- Shove everything in storage and return the indices:
- in eaddrpos for sender+recipients, in mxipind for the IPs to connect to.
-
- Also, fuck DNS for requiring so many small allocations and data copies.
-
- Also, fuck DNS.
- */
-
-void dns_stuff (char const *host, char const *const *eaddr, unsigned int n, size_t *eaddrpos, genalloc *mxipind, stralloc *storage, unsigned int timeoutdns, char const *ipme4, unsigned int n4, char const *ipme6, unsigned int n6, uint32_t flags)
-{
- skadns_t a = SKADNS_ZERO ;
- genalloc mxipi = GENALLOC_ZERO ; /* mxipinfo */
- tain deadline ;
- unsigned int pending = 0 ;
- uint16_t mxn = 0 ;
- uint16_t mxid = UINT16_MAX ;
- cnameinfo cnames[n] ;
-
- tain_addsec_g(&deadline, timeoutdns) ;
- if (!skadns_startf_g(&a, &deadline))
- qmailr_tempsys("Unable to start asynchronous DNS helper") ;
-
- for (unsigned int i = 0 ; i < n ; i++)
- {
- char const *at = strrchr(eaddr[i], '@') ;
- cnames[i].sa = stralloc_zero ;
- if (at)
- {
- s6dns_domain_t q ;
- size_t len = strlen(at+1) ;
- cnames[i].atpos = at - eaddr[i] ;
- if (!stralloc_catb(&cnames[i].sa, at+1, len)) dienomem() ;
- if (!s6dns_domain_fromstring_noqualify_encode(&q, at+1, len))
- qmailr_tempsys("Unable to DNS-encode recipient domain") ;
- if (!skadns_send_g(&a, &cnames[i].id, &q, S6DNS_T_CNAME, &deadline, &deadline))
- qmailr_tempsys("Unable to send CNAME DNS query") ;
- cnames[i].count = 1 ;
- pending++ ;
- }
- else
- {
- cnames[i].id = UINT16_MAX ;
- cnames[i].count = 0 ;
- cnames[i].atpos = strlen(eaddr[i]) ;
- }
- }
-
- if (flags & 1)
- {
- s6dns_domain_t q ;
- if (!s6dns_domain_fromstring_noqualify_encode(&q, host, strlen(host)))
- qmailr_tempsys("Unable to DNS-encode host domain") ;
- if (!skadns_send_g(&a, &mxid, &q, S6DNS_T_MX, &deadline, &deadline))
- qmailr_tempsys("Unable to send MX DNS query") ;
- pending++ ;
- }
- else
- {
- mxn = 1 ;
- pending += use_host_as_mx(&a, host, &mxipi, &deadline) ;
- }
-
- while (pending)
- {
- uint16_t *ids ;
- iopause_fd x = { .fd = skadns_fd(&a), .events = IOPAUSE_READ } ;
- int r = iopause_g(&x, 1, &deadline) ;
- if (r == -1) qmailr_tempsys("Unable to iopause") ;
- if (!r) qmailr_tempsys("Timed out waiting for DNS") ;
- r = skadns_update(&a) ;
- if (r == -1) qmailr_tempsys("Unable to read DNS answers") ;
- ids = genalloc_s(uint16_t, &a.list) ;
- for (size_t j = 0 ; j < genalloc_len(uint16_t, &a.list) ; j++)
- {
- char const *packet = skadns_packet(&a, ids[j]) ;
- uint16_t packetlen = skadns_packetlen(&a, ids[j]) ;
- if (!packet) qmailr_tempsys("DNS packet reading error") ;
-
- if (ids[j] == mxid) /* return from MX query */
- {
- s6dns_message_header_t h ;
- genalloc mxes = GENALLOC_ZERO ; /* s6dns_message_rr_mx_t */
- r = s6dns_message_parse(&h, packet, packetlen, &s6dns_message_parse_answer_mx, &mxes) ;
- if (r == -1) qmailr_tempsys("DNS packet parsing error") ;
- if (!r)
- {
- if (errno == EBUSY || errno == EIO) qmailr_temp("Temporary DNS error while resolving MX") ;
- else qmailr_perm("DNS CNAME resolution error") ;
- }
- skadns_release(&a, ids[j]) ;
- pending-- ;
- mxid = UINT16_MAX ;
- if (r >= 2) /* we have MXes, ask for their IPs */
- {
- s6dns_message_rr_mx_t *mxs = genalloc_s(s6dns_message_rr_mx_t, &mxes) ;
- mxn = genalloc_len(s6dns_message_rr_mx_t, &mxes) ;
- if (!genalloc_readyplus(mxipinfo, &mxipi, mxn)) dienomem() ;
- qsort(mxs, mxn, sizeof(s6dns_message_rr_mx_t), &mx_cmp) ;
- for (unsigned int i = 0 ; i < mxn ; i++)
- {
- mxipinfo *p = genalloc_s(mxipinfo, &mxipi) + i ;
- p->ip4 = p->ip6 = stralloc_zero ;
- if (!skadns_send_g(&a, &p->id4, &mxs[i].exchange, S6DNS_T_A, &deadline, &deadline))
- qmailr_tempsys("Unable to send A DNS query") ;
- pending++ ;
-#ifdef SKALIBS_IPV6_ENABLED
- if (!skadns_send_g(&a, &p->id6, &mxs[i].exchange, S6DNS_T_AAAA, &deadline, &deadline))
- qmailr_tempsys("Unable to send AAAA DNS query") ;
- pending++ ;
-#endif
- }
- genalloc_free(s6dns_message_rr_mx_t, &mxes) ;
- }
- else
- {
- mxn = 1 ;
- pending += use_host_as_mx(&a, host, &mxipi, &deadline) ;
- }
- continue ;
- }
-
- for (unsigned int i = 0 ; i < n ; i++) if (ids[j] == cnames[i].id) /* return from CNAME query */
- {
- s6dns_message_header_t h ;
- s6dns_dpag_t dlist = { .ds = GENALLOC_ZERO, .rtype = S6DNS_T_CNAME } ;
- r = s6dns_message_parse(&h, packet, packetlen, &s6dns_message_parse_answer_domain, &dlist) ;
- if (r == -1) qmailr_tempsys("DNS packet parsing error") ;
- if (!r)
- {
- if (errno == EBUSY || errno == EIO) qmailr_temp("Temporary DNS error while resolving CNAME") ;
- else qmailr_perm("DNS CNAME resolution error") ;
- }
- skadns_release(&a, ids[j]) ;
- pending-- ;
- if (r >= 2) /* it's a CNAME, loop on it */
- {
- s6dns_domain_t *domain = genalloc_s(s6dns_domain_t, &dlist.ds) ;
- if (cnames[i].count++ >= 100) qmailr_temp("DNS CNAME loop") ;
- if (!skadns_send_g(&a, &cnames[i].id, domain, S6DNS_T_CNAME, &deadline, &deadline))
- qmailr_tempsys("Unable to send CNAME DNS query") ;
- pending++ ;
- if (!stralloc_ready(&cnames[i].sa, 256)) dienomem() ;
- s6dns_domain_decode(domain) ;
- cnames[i].sa.len = s6dns_domain_tostring(cnames[i].sa.s, 256, domain) ;
- genalloc_free(s6dns_domain_t, &dlist.ds) ;
- }
- else cnames[i].id = UINT16_MAX ; /* that's the canonical host in cnames[i].sa */
- continue ;
- }
-
- for (unsigned int i = 0 ; i < mxn ; i++)
- {
- mxipinfo *p = genalloc_s(mxipinfo, &mxipi) + i ;
- if (ids[j] == p->id4)
- {
- s6dns_message_header_t h ;
- r = s6dns_message_parse(&h, packet, packetlen, &s6dns_message_parse_answer_a, &p->ip4) ;
- if (r == -1) qmailr_tempsys("DNS packet parsing error") ;
- if (!r)
- {
- if (errno == EBUSY || errno == EIO) qmailr_temp("Temporary DNS error while resolving A") ;
- else qmailr_perm("DNS A resolution error") ;
- }
- skadns_release(&a, ids[j]) ;
- pending-- ;
- p->id4 = UINT16_MAX ;
- for (unsigned int k = 0 ; k < p->ip4.len ; k += 4)
- {
- if (bsearch(p->ip4.s + k, ipme4, n4, 4, &qmailr_memcmp4))
- {
- memmove(p->ip4.s + k, p->ip4.s + p->ip4.len - 4, 4) ;
- p->ip4.len -= 4 ;
- k -= 4 ;
- }
- }
- }
-#ifdef SKALIBS_IPV6_ENABLED
- else if (ids[j] == p->id6)
- {
- s6dns_message_header_t h ;
- r = s6dns_message_parse(&h, packet, packetlen, &s6dns_message_parse_answer_aaaa, &p->ip6) ;
- if (r == -1) qmailr_tempsys("DNS packet parsing error") ;
- if (!r)
- {
- if (errno == EBUSY || errno == EIO) qmailr_temp("Temporary DNS error while resolving AAAA") ;
- else qmailr_perm("DNS AAAA resolution error") ;
- }
- skadns_release(&a, ids[j]) ;
- pending-- ;
- p->id6 = UINT16_MAX ;
- for (unsigned int k = 0 ; k < p->ip6.len ; k += 16)
- {
- if (bsearch(p->ip6.s + k, ipme6, n6, 16, &qmailr_memcmp16))
- {
- memmove(p->ip6.s + k, p->ip6.s + p->ip6.len - 16, 16) ;
- p->ip6.len -= 16 ;
- k -= 16 ;
- }
- }
- }
-#endif
- }
- }
- }
- skadns_end(&a) ; /* we done buddy */
-
- for (unsigned int i = 0 ; i < n ; i++)
- {
- eaddrpos[i] = storage->len ;
- if (!qmailr_box_encode(eaddr[i], cnames[i].atpos, storage)) dienomem() ;
- if (cnames[i].count)
- {
- if (!stralloc_catb(storage, "@", 1)) dienomem() ;
- if (!stralloc_catb(storage, cnames[i].sa.s, cnames[i].sa.len)) dienomem() ;
- stralloc_free(&cnames[i].sa) ;
- }
- if (!stralloc_0(storage)) dienomem() ;
- }
-
- if (!genalloc_readyplus(mxip, mxipind, mxn)) dienomem() ;
- for (unsigned int i = 0 ; i < mxn ; i++)
- {
- mxip data ;
- mxipinfo *p = genalloc_s(mxipinfo, &mxipi) + i ;
- data.n4 = p->ip4.len >> 2 ;
- data.pos4 = storage->len ;
- if (!stralloc_catb(storage, p->ip4.s, p->ip4.len)) dienomem() ;
- stralloc_free(&p->ip4) ;
-#ifdef SKALIBS_IPV6_ENABLED
- data.n6 = p->ip6.len >> 4 ;
- data.pos6 = storage->len ;
- if (!stralloc_catb(storage, p->ip6.s, p->ip6.len)) dienomem() ;
- stralloc_free(&p->ip6) ;
- genalloc_catb(mxip, mxipind, &data, 1) ;
-#endif
- }
- genalloc_free(mxipinfo, &mxipi) ;
-}
diff --git a/src/qmail-smtpc/qmail-smtpc.c b/src/qmail-smtpc/qmail-smtpc.c
deleted file mode 100644
index 0e0b11b..0000000
--- a/src/qmail-smtpc/qmail-smtpc.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* ISC license. */
-
-#include <string.h>
-#include <stdint.h>
-#include <unistd.h>
-
-#include <skalibs/cdb.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/sig.h>
-#include <skalibs/tai.h>
-#include <skalibs/ip46.h>
-
-#include <smtpd-starttls-proxy/config.h>
-#include "qmailr.h"
-#include "qmail-smtpc.h"
-
-#define dieusage() qmailr_perm("qmail-remote was invoked improperly")
-
-int main (int argc, char const *const *argv)
-{
- stralloc storage = STRALLOC_ZERO ;
- stralloc ipme4 = STRALLOC_ZERO ;
- stralloc ipme6 = STRALLOC_ZERO ;
- qmailr_tls qt = QMAILR_TLS_ZERO ;
- smtproutes routes = SMTPROUTES_ZERO ;
- unsigned int timeoutconnect = 60, timeoutremote = 1200 ;
- char const *host ;
- size_t mepos, helopos, hostpos = 0 ;
- uint16_t port = 25 ;
- int r ;
-
- if (argc-- < 4) dieusage() ;
- argv++ ;
- if (chdir(SMTPD_STARTTLS_PROXY_QMAIL_HOME) == -1) qmailr_temp("Unable to chdir to " SMTPD_STARTTLS_PROXY_QMAIL_HOME) ;
- if (sig_altignore(SIGPIPE) == -1) qmailr_tempsys("Unable to ignore SIGPIPE") ;
- host = *argv++ ; argc-- ;
- tain_now_set_stopwatch_g() ;
-
-
- /* init control */
-
- r = qmailr_control_read("control/me", &storage, &mepos) ;
- if (r == -1) qmailr_tempsys("Unable to read control/me") ;
- else if (!r) qmailr_temp("Invalid control/me") ;
-
- r = qmailr_control_read("control/helohost", &storage, &helopos) ;
- if (r == -1) qmailr_tempsys("Unable to read control/helohost") ;
- else if (!r) helopos = mepos ;
-
- r = qmailr_control_readint("control/timeoutconnect", &timeoutconnect, &storage) ;
- if (r == -1) qmailr_tempsys("Unable to read control/timeoutconnect") ;
- r = qmailr_control_readint("control/timeoutremote", &timeoutremote, &storage) ;
- if (r == -1) qmailr_tempsys("Unable to read control/timeoutremote") ;
-
- if (!qmailr_control_readiplist("control/ipme", &ipme4, &ipme6))
- qmailr_tempsys("Unable to read control/ipme") ;
- stralloc_shrink(&ipme4) ;
- stralloc_shrink(&ipme6) ;
- qsort(ipme4.s, ipme4.len >> 2, 4, &qmailr_memcmp4) ;
- qsort(ipme6.s, ipme6.len >> 4, 16, &qmailr_memcmp16) ;
-
- if (!qmailr_tls_init(&qt, &storage))
- qmailr_tempsys("Unable to read TLS control files") ;
-
- if (smtproutes_init(&routes))
- {
- if (!smtproutes_match(&routes, host, &storage, &hostpos, &port))
- {
- size_t hostlen = strlen(host) ;
- for (size_t i = 0 ; i < hostlen ; i++) if (host[i] == '.')
- if (smtproutes_match(&routes, argv[1], &storage, &hostpos, &port)) break ;
- if (!hostpos) smtproutes_match(&routes, "", &storage, &hostpos, &port) ;
- }
- smtproutes_free(&routes) ;
- }
-
- {
- genalloc mxipind = GENALLOC_ZERO ;
- size_t eaddrpos[argc] ;
- dns_stuff(hostpos ? storage.s + hostpos : host, argv, argc, eaddrpos, &mxipind, &storage, timeoutconnect, ipme4.s, ipme4.len >> 2, ipme6.s, ipme6.len >> 4, !hostpos) ;
-
- }
-
-
- _exit(0) ;
-}
diff --git a/src/qmail-smtpc/qmail-smtpc.h b/src/qmail-smtpc/qmail-smtpc.h
deleted file mode 100644
index 29aa792..0000000
--- a/src/qmail-smtpc/qmail-smtpc.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* ISC license. */
-
-#ifndef QMAIL_SMTPC_H
-#define QMAIL_SMTPC_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <skalibs/cdb.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/genalloc.h>
-
-#include "qmailr.h"
-
-#define dienomem() qmailr_tempsys("Unable to grow stralloc")
-
-
-/* dns */
-
-typedef struct mxip_s mxip, *mxip_ref ;
-struct mxip_s
-{
- size_t pos4 ;
- size_t pos6 ;
- uint16_t n4 ;
- uint16_t n6 ;
-} ;
-#define MXIP_ZERO { 0 }
-
-extern void dns_stuff (char const *, char const *const *, unsigned int, size_t *, genalloc *, stralloc *, unsigned int, char const *, unsigned int, char const *, unsigned int, uint32_t) ;
-
-
-/* smtproutes */
-
-typedef struct smtproutes_s smtproutes ;
-struct smtproutes_s
-{
- cdb map ;
-} ;
-#define SMTPROUTES_ZERO { .map = CDB_ZERO }
-
-extern int smtproutes_init (smtproutes *) ;
-extern int smtproutes_match (smtproutes const *, char const *, stralloc *, size_t *, uint16_t *) ;
-extern void smtproutes_free (smtproutes *) ;
-
-#endif
diff --git a/src/qmail-smtpc/qmailr.h b/src/qmail-smtpc/qmailr.h
deleted file mode 100644
index 08c4f41..0000000
--- a/src/qmail-smtpc/qmailr.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* ISC license. */
-
-#ifndef QMAILR_H
-#define QMAILR_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <skalibs/gccattributes.h>
-#include <skalibs/tai.h>
-#include <skalibs/stralloc.h>
-
-
-/* qmailr_error */
-
-extern void qmailr_diev (int, char const *const *, unsigned int) gccattr_noreturn ;
-extern void qmailr_dievsys (char const *const *, unsigned int) gccattr_noreturn ;
-extern void qmailr_die (int, char const *) gccattr_noreturn ;
-extern void qmailr_diesys (char const *) gccattr_noreturn ;
-
-#define qmailr_temp(s) qmailr_die(0, (s))
-#define qmailr_tempv(v, n) qmailr_diev(0, (v), n)
-#define qmailr_tempsys(s) qmailr_diesys(s)
-#define qmailr_tempvsys(v, n) qmailr_dievsys(v, n)
-#define qmailr_perm(s) qmailr_die(1, (s))
-#define qmailr_permv(v, n) qmailr_diev(1, (v), n)
-
-
-/* qmailr_utils */
-
-extern int qmailr_memcmp4 (void const *, void const *) ;
-extern int qmailr_memcmp16 (void const *, void const *) ;
-extern int qmailr_box_encode (char const *, size_t, stralloc *) ;
-
-
-/* qmailr_tcpto */
-
-extern int qmailr_tcpto_match (char const *, int) ;
-extern int qmailr_tcpto_update (char const *, int, int) ;
-
-
-/* qmailr_control */
-
-extern int qmailr_control_read (char const *, stralloc *, size_t *) ;
-extern int qmailr_control_readint (char const *file, unsigned int *, stralloc *) ;
-extern int qmailr_control_readiplist (char const *, stralloc *, stralloc *) ;
-
-
-/* qmailr_tls */
-
-typedef struct qmailr_tls_s qmailr_tls, *qmailr_tls_ref ;
-struct qmailr_tls_s
-{
- size_t tapos ;
- size_t certpos ;
- size_t keypos ;
- uint8_t strictness : 2 ;
- uint8_t flagtls : 1 ;
- uint8_t flagtadir : 1 ;
- uint8_t flagclientcert : 1 ;
-} ;
-#define QMAILR_TLS_ZERO { 0 }
-
-extern int qmailr_tls_init (qmailr_tls *, stralloc *) ;
-
-#endif
diff --git a/src/qmail-smtpc/qmailr_control.c b/src/qmail-smtpc/qmailr_control.c
deleted file mode 100644
index 706b0d9..0000000
--- a/src/qmail-smtpc/qmailr_control.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/* ISC license. */
-
-#include <stddef.h>
-#include <errno.h>
-
-#include <skalibs/types.h>
-#include <skalibs/allreadwrite.h>
-#include <skalibs/buffer.h>
-#include <skalibs/fmtscan.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/skamisc.h>
-
-#include "qmailr.h"
-
-#include <skalibs/posixishard.h>
-
-int qmailr_control_read (char const *file, stralloc *sa, size_t *pos)
-{
- int fd = openc_readb(file) ;
- if (fd == -1) return errno == ENOENT ? (errno = 0, 0) : -1 ;
-
- char buf[4096] ;
- size_t r = allread(fd, buf, 4096) ;
- fd_close(fd) ;
- if (r == 4096) return (errno = ENAMETOOLONG, -1) ;
- if (!r) return 0 ;
- if (buf[r-1] == '\n') r-- ;
- if (!r) return 0 ;
- if (!stralloc_readyplus(sa, r+1)) return -1 ;
- *pos = sa->len ;
- stralloc_catb(sa, buf, r) ; stralloc_0(sa) ;
- return 1 ;
-}
-
-int qmailr_control_readint (char const *file, unsigned int *x, stralloc *sa)
-{
- size_t pos ;
- int r = qmailr_control_read(file, sa, &pos) ;
- if (r <= 0) return r ;
- sa->len = pos ;
- if (!uint0_scan(sa->s + sa->len, x)) return (errno = EPROTO, 0) ;
- return 1 ;
-}
-
-int qmailr_control_readiplist (char const *file, stralloc *ip4, stralloc *ip6)
-{
- int fd = openc_readb(file) ;
- if (fd == -1) return errno == ENOENT ? (errno = 0, 0) : -1 ;
-
- size_t pos4 = ip4->len, pos6 = ip6->len ;
- char buf[4096] ;
- buffer b = BUFFER_INIT(&buffer_read, fd, buf, 4096) ;
-
- for (;;)
- {
- char line[128] ;
- char ip[16] ;
- size_t len = 0 ;
- int r = getlnmax(&b, line, 127, &len, '\n') ;
- if (r == -1) goto err ;
- if (!r) break ;
- if (!len) continue ;
- if (line[len-1] != '\n') line[len++] = '\n' ;
- if (ip6_scan(line, ip) == len-1)
- {
- if (!stralloc_catb(ip6, ip, 16)) goto err ;
- }
- else if (ip4_scan(line, ip) == len-1)
- {
- if (!stralloc_catb(ip4, ip, 4)) goto err ;
- }
- else goto errinval ;
- }
- return 1 ;
-
- errinval:
- errno = EINVAL ;
- err:
- ip4->len = pos4 ; ip6->len = pos6 ;
- return 0 ;
-}
diff --git a/src/qmail-smtpc/qmailr_error.c b/src/qmail-smtpc/qmailr_error.c
deleted file mode 100644
index fcdce54..0000000
--- a/src/qmail-smtpc/qmailr_error.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* ISC license. */
-
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <skalibs/buffer.h>
-
-#include <smtpd-starttls-proxy/config.h>
-
-void qmailr_diev (int permanent, char const *const *v, unsigned int n)
-{
- buffer_put(buffer_1small, permanent ? "D" : "Z", 1) ;
- while (n--) buffer_puts(buffer_1small, *v++) ;
- buffer_putflush(buffer_1small, "\n", 2) ;
- _exit(0) ;
-}
-
-void qmailr_dievsys (char const *const *v, unsigned int n)
-{
- char const *se = strerror(errno) ;
- buffer_put(buffer_1small, "Z", 1) ;
- while (n--) buffer_puts(buffer_1small, *v++) ;
- buffer_put(buffer_1small, ": ", 2) ;
- buffer_puts(buffer_1small, se) ;
- buffer_putflush(buffer_1small, "\n", 2) ;
- _exit(0) ;
-}
-
-void qmailr_die (int permanent, char const *msg)
-{
- qmailr_diev(permanent, &msg, 1) ;
-}
-
-void qmailr_diesys (char const *msg)
-{
- qmailr_dievsys(&msg, 1) ;
-}
diff --git a/src/qmail-smtpc/qmailr_tcpto.c b/src/qmail-smtpc/qmailr_tcpto.c
deleted file mode 100644
index f90d1d0..0000000
--- a/src/qmail-smtpc/qmailr_tcpto.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/* ISC license. */
-
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include <skalibs/uint32.h>
-#include <skalibs/uint64.h>
-#include <skalibs/allreadwrite.h>
-#include <skalibs/cdb.h>
-#include <skalibs/tai.h>
-#include <skalibs/djbunix.h>
-
-#include <smtpd-starttls-proxy/config.h>
-#include "qmailr.h"
-
-#include <skalibs/posixishard.h>
-
-
-/*
- tcpto implementation, should be compatible with qmail-tcpto.
- Assumes the 4 unused bytes at the end of a record are there to
- accommodate 64-bit time_t. Which we use. But qmail-tcpto does
- not, so you should patch that before 2038.
- Has ipv6 support, storing v6 records in a different file.
- Unlike qmail's tcpto, we assume the records are sorted by IP.
- This makes it easy to look for a record with bsearch. We
- keep records sorted with every modification, and we aggressively
- cut empty ones from the file.
- For the match function, not sure what is faster between mmapping and
- simple reading. Currently we mmap to save private/dirty RAM, but
- that holds the lock longer; it should be ok because we switched to
- a shared lock for this (unsure why djb didn't).
-*/
-
-int qmailr_tcpto_match (char const *ip, int is6)
-{
- char const *file = is6 ? SMTPD_STARTTLS_PROXY_QMAIL_HOME "/run/qmail-remote/tcpto6" : SMTPD_STARTTLS_PROXY_QMAIL_HOME "/queue/lock/tcpto" ;
- uint32_t iplen = is6 ? 16 : 4 ;
- uint32_t width = iplen + 12 ;
- int r = 0 ;
- char const *p ;
- cdb c ; /* XXX: not a cdb, we're just using the mmap wrapper */
- int fd = openc_read(file) ;
-
- if (fd == -1) return -1 ;
- if (fd_lock(fd, 0, 0) == -1) goto err ;
- if (!cdb_init_fromfd(&c, fd)) goto err ;
- if (c.size % width) goto errproto ;
- p = bsearch(ip, c.map, c.size / width, width, is6 ? &qmailr_memcmp16 : &qmailr_memcmp4) ;
- if (p)
- {
- if (p[iplen] >= 2)
- {
- tai when ;
- uint64_t x ;
- uint64_unpack(p + iplen + 4, &x) ;
- tai_u64(&when, x) ;
- tai_sub(&when, tain_secp(&STAMP), &when) ;
- r = tai_sec(&when) < ((60 + (getpid() & 31)) << 6) ; /* don't ask me, ask djb */
- }
- }
- cdb_free(&c) ;
- fd_close(fd) ;
- return r ;
-
- errproto:
- errno = EPROTO ;
- err:
- fd_close(fd) ;
- return -1 ;
-}
-
-int qmailr_tcpto_update (char const *ip, int is6, int problem)
-{
- char const *file = is6 ? SMTPD_STARTTLS_PROXY_QMAIL_HOME "/run/qmail-remote/tcpto6" : SMTPD_STARTTLS_PROXY_QMAIL_HOME "/queue/lock/tcpto" ;
- uint32_t iplen = is6 ? 16 : 4 ;
- uint32_t width = iplen + 12 ;
- uint32_t n ;
- char *p = 0 ;
- struct stat st ;
- int fdr ;
- int fdw = openc_create(file) ;
-
- if (fdw == -1) return 0 ;
- if (fd_lock(fdw, 1, 0) == -1) goto err ;
- fdr = openc_read(file) ;
- if (fdr == -1) goto err ;
- if (fstat(fdr, &st) == -1) goto err0 ;
- if (st.st_size % width) goto errproto ;
- n = st.st_size / width ;
-
- {
- char buf[(n+1) * width] ; /* relax, it won't bite */
- if (n)
- {
- if (allread(fdr, buf, st.st_size) < st.st_size) goto err0 ;
- memset(buf + st.st_size, 0, width) ;
- p = bsearch(ip, buf, n, width, is6 ? &qmailr_memcmp16 : &qmailr_memcmp4) ;
- if (p)
- {
- if (problem)
- {
- tai when ;
- uint64_t x ;
- uint64_unpack(p + iplen + 4, &x) ;
- tai_u64(&when, x) ;
- tai_sub(&when, tain_secp(&STAMP), &when) ;
- if (tai_sec(&when) < 120) p = 0 ;
- else
- {
- if (++p[iplen] > 10) p[iplen] = 10 ;
- x = tai_sec(tain_secp(&STAMP)) - TAI_MAGIC ;
- uint64_pack(p + iplen + 4, x) ;
- }
- }
- else p[iplen] = 0 ;
- }
- }
- else if (problem)
- {
- uint64_t x = tai_sec(tain_secp(&STAMP)) - TAI_MAGIC ;
- p = buf + n++ * width ;
- memcpy(p, ip, iplen) ;
- p[iplen] = 1 ;
- memset(p + iplen + 1, 0, 3) ;
- uint64_pack(p + iplen + 4, x) ;
- }
- fd_close(fdr) ;
-
- if (p)
- {
- for (uint32_t i = 0 ; i < n ; i++)
- if (!buf[i * width + iplen])
- memcpy(buf + i * width, buf + --n * width, width) ;
- if (n)
- {
- qsort(buf, n, width, is6 ? &qmailr_memcmp16 : &qmailr_memcmp4) ;
- if (allwrite(fdw, buf, n * width) < n * width) goto err ;
- }
- if (ftruncate(fdw, n * width) == -1) goto err ;
- }
- }
-
- fd_close(fdw) ;
- return 1 ;
-
- errproto:
- errno = EPROTO ;
- err0:
- fd_close(fdr) ;
- err:
- fd_close(fdw) ;
- return 0 ;
-}
diff --git a/src/qmail-smtpc/qmailr_tls.c b/src/qmail-smtpc/qmailr_tls.c
deleted file mode 100644
index 6e09a82..0000000
--- a/src/qmail-smtpc/qmailr_tls.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* ISC license. */
-
-#include <stddef.h>
-
-#include <smtpd-starttls-proxy/config.h>
-#include "qmailr.h"
-
-int qmailr_tls_init (qmailr_tls *qt, stralloc *sa)
-{
- static char const *tafile = SMTPD_STARTTLS_PROXY_QMAIL_HOME "/control/trustanchors" ;
- static char const *certfile = SMTPD_STARTTLS_PROXY_QMAIL_HOME "/control/clientcert" ;
- static char const *keyfile = SMTPD_STARTTLS_PROXY_QMAIL_HOME "/control/clientkey" ;
- static char const *strictfile = SMTPD_STARTTLS_PROXY_QMAIL_HOME "/control/tlsstrictness" ;
-
- qmailr_tls tmp = QMAILR_TLS_ZERO ;
- size_t sabase = sa->len ;
- int r = qmailr_control_read(tafile, sa, &tmp.tapos) ;
- if (r == -1) return 0 ;
- if (r)
- {
- unsigned int strictness = 0 ;
- tmp.flagtls = 1 ;
- if (sa->s[sa->len - 2] == '/')
- {
- sa->s[--sa->len - 1] = 0 ;
- tmp.flagtadir = 1 ;
- }
- r = qmailr_control_read(certfile, sa, &tmp.certpos) ;
- if (r == -1) goto err ;
- if (r)
- {
- r = qmailr_control_read(keyfile, sa, &tmp.keypos) ;
- if (r == -1) goto err ;
- if (r) tmp.flagclientcert = 1 ;
- }
- r = qmailr_control_readint(strictfile, &strictness, sa) ;
- if (r == -1) goto err ;
- tmp.strictness = strictness & 3 ;
- }
-
- *qt = tmp ;
- return 1 ;
-
- err:
- sa->len = sabase ;
- return 0 ;
-}
diff --git a/src/qmail-smtpc/qmailr_utils.c b/src/qmail-smtpc/qmailr_utils.c
deleted file mode 100644
index deeff46..0000000
--- a/src/qmail-smtpc/qmailr_utils.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* ISC license. */
-
-#include <string.h>
-
-#include <skalibs/bitarray.h>
-#include <skalibs/stralloc.h>
-
-#include "qmailr.h"
-
-int qmailr_memcmp4 (void const *a, void const *b)
-{
- return memcmp(a, b, 4) ;
-}
-
-int qmailr_memcmp16 (void const *a, void const *b)
-{
- return memcmp(a, b, 16) ;
-}
-
-static inline int needsquoting (char const *s, size_t len)
-{
- static unsigned char const badchar[32] =
- {
- 0xff, 0xff, 0xff, 0xff,
- 0x05, 0x13, 0x00, 0x5c,
- 0x01, 0x00, 0x00, 0x38,
- 0x00, 0x00, 0x00, 0x80,
- 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff,
- } ;
- if (!len) return 1 ;
- if (s[0] == '.' || s[len - 1] == '.') return 1 ;
- for (size_t i = 0 ; i < len ; i++)
- {
- if (bitarray_peek(badchar, (unsigned char)s[i])) return 1 ;
- if (i + 2 < len && s[i] == '.' && s[i+1] == '.') return 1 ;
- }
- return 0 ;
-}
-
-int qmailr_box_encode (char const *s, size_t len, stralloc *storage)
-{
- if (needsquoting(s, len))
- {
- size_t j = storage->len ;
- if (!stralloc_readyplus(storage, 2 + (len << 1))) return 0 ;
- storage->s[j++] = '"' ;
- for (size_t i = 0 ; i < len ; i++)
- {
- if (strchr("\"\\\r\n", s[i])) storage->s[j++] = '\\' ;
- storage->s[j++] = s[i] ;
- }
- storage->s[j++] = '"' ;
- storage->len = j ;
- }
- else if (!stralloc_catb(storage, s, len)) return 0 ;
- return 1 ;
-}
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) ;
-}