[rt-commit] r215 - in /redwax-tool/trunk: ChangeLog configure.ac redwax-tool.c redwax-tool.h redwax-tool.spec.in redwax_ldns.c redwax_openssl.c redwax_unbound.c

rt-commit at redwax.eu rt-commit at redwax.eu
Wed Apr 2 15:10:28 CEST 2025


Author: minfrin at redwax.eu
Date: Wed Apr  2 15:10:26 2025
New Revision: 215

Log:
Add --tls-in to read certificates from endpoints
pointed to by A and AAAA DNS records.

Modified:
    redwax-tool/trunk/ChangeLog
    redwax-tool/trunk/configure.ac
    redwax-tool/trunk/redwax-tool.c
    redwax-tool/trunk/redwax-tool.h
    redwax-tool/trunk/redwax-tool.spec.in
    redwax-tool/trunk/redwax_ldns.c
    redwax-tool/trunk/redwax_openssl.c
    redwax-tool/trunk/redwax_unbound.c

Modified: redwax-tool/trunk/ChangeLog
==============================================================================
--- redwax-tool/trunk/ChangeLog	(original)
+++ redwax-tool/trunk/ChangeLog	Wed Apr  2 15:10:26 2025
@@ -1,3 +1,9 @@
+
+Changes with v0.9.10
+
+ *) Add --tls-in to read certificates from endpoints
+    pointed to by A and AAAA DNS records.
+    [Graham Leggett]
 
 Changes with v0.9.9
 

Modified: redwax-tool/trunk/configure.ac
==============================================================================
--- redwax-tool/trunk/configure.ac	(original)
+++ redwax-tool/trunk/configure.ac	Wed Apr  2 15:10:26 2025
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT(redwax-tool, 0.9.9, minfrin at sharp.fm)
+AC_INIT(redwax-tool, 0.9.10, minfrin at sharp.fm)
 AC_CONFIG_AUX_DIR(build-aux)
 AC_CONFIG_MACRO_DIRS([m4])
 AM_INIT_AUTOMAKE([dist-bzip2])

Modified: redwax-tool/trunk/redwax-tool.c
==============================================================================
--- redwax-tool/trunk/redwax-tool.c	(original)
+++ redwax-tool/trunk/redwax-tool.c	Wed Apr  2 15:10:26 2025
@@ -98,6 +98,8 @@
         APR_HOOK_LINK(process_pkcs12_in)
         APR_HOOK_LINK(complete_keychain_in)
         APR_HOOK_LINK(process_keychain_in)
+        APR_HOOK_LINK(set_tls_in)
+        APR_HOOK_LINK(process_tls_in)
         APR_HOOK_LINK(complete_filter)
         APR_HOOK_LINK(process_filter)
         APR_HOOK_LINK(complete_nss_out)
@@ -183,6 +185,10 @@
         (redwax_tool_t * r, const char *arg), (r, arg), DECLINED)
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, complete_keychain_in,
         (redwax_tool_t * r, const char *url, apr_hash_t *urls), (r, url, urls), DECLINED)
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, set_tls_in,
+        (redwax_tool_t * r, const char *arg), (r, arg), DECLINED)
+APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_tls_in,
+        (redwax_tool_t * r, redwax_dns_t *dns), (r, dns), DECLINED)
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(rt, REDWAX, int, complete_filter,
         (redwax_tool_t * r, apr_hash_t *filters), (r, filters), OK, DECLINED)
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(rt, REDWAX, int, process_filter,
@@ -257,69 +263,70 @@
 #define REDWAX_TOOL_PKCS11_MODULE_IN 259
 #define REDWAX_TOOL_PKCS12_IN 260
 #define REDWAX_TOOL_KEYCHAIN_IN 261
-#define REDWAX_TOOL_FILTER 262
-#define REDWAX_TOOL_FILTER_EMAIL 263
-#define REDWAX_TOOL_FILTER_HOSTNAME 264
-#define REDWAX_TOOL_FILTER_IP 265
-#define REDWAX_TOOL_FILTER_CURRENT 266
-#define REDWAX_TOOL_FILTER_DATE 267
-#define REDWAX_TOOL_FILTER_EXPIRY 268
-#define REDWAX_TOOL_FILTER_DANE 269
-#define REDWAX_TOOL_FILTER_PURPOSE 270
-#define REDWAX_TOOL_FILTER_VERIFY_PARAM 271
-#define REDWAX_TOOL_FILTER_VERIFY_TLSA 272
-#define REDWAX_TOOL_FILTER_VERIFY_SMIMEA 273
-#define REDWAX_TOOL_CERT_OUT 274
-#define REDWAX_TOOL_NO_CERT_OUT 275
-#define REDWAX_TOOL_CHAIN_OUT 276
-#define REDWAX_TOOL_NO_CHAIN_OUT 277
-#define REDWAX_TOOL_ROOT_OUT 278
-#define REDWAX_TOOL_NO_ROOT_OUT 279
-#define REDWAX_TOOL_TRUST_OUT 280
-#define REDWAX_TOOL_NO_TRUST_OUT 281
-#define REDWAX_TOOL_CRL_OUT 282
-#define REDWAX_TOOL_NO_CRL_OUT 283
-#define REDWAX_TOOL_PARAM_OUT 284
-#define REDWAX_TOOL_NO_PARAM_OUT 285
-#define REDWAX_TOOL_KEY_IN 286
-#define REDWAX_TOOL_NO_KEY_IN 287
-#define REDWAX_TOOL_KEY_OUT 288
-#define REDWAX_TOOL_NO_KEY_OUT 289
-#define REDWAX_TOOL_AUTO_OUT 290
-#define REDWAX_TOOL_NO_AUTO_OUT 291
-#define REDWAX_TOOL_SECRET_SUFFIX_IN 292
-#define REDWAX_TOOL_SECRET_SUFFIX_OUT 293
-#define REDWAX_TOOL_SECRET_TOKEN_IN 294
-#define REDWAX_TOOL_SECRET_TOKEN_OUT 295
-#define REDWAX_TOOL_LABEL_OUT 296
-#define REDWAX_TOOL_NSS_OUT 297
-#define REDWAX_TOOL_NSS_SLOT_OUT 298
-#define REDWAX_TOOL_DER_OUT 299
-#define REDWAX_TOOL_PEM_OUT 300
-#define REDWAX_TOOL_PKCS12_OUT 301
-#define REDWAX_TOOL_PKCS11_OUT 302
-#define REDWAX_TOOL_PKCS11_MODULE_OUT 303
-#define REDWAX_TOOL_METADATA_OUT 304
-#define REDWAX_TOOL_METADATA_THRESHOLD 305
-#define REDWAX_TOOL_FORMAT_OUT 306
-#define REDWAX_TOOL_CALENDAR_OUT 307
-#define REDWAX_TOOL_CALENDAR_ALARM 308
-#define REDWAX_TOOL_REMINDER_OUT 309
-#define REDWAX_TOOL_JWKS_OUT 310
-#define REDWAX_TOOL_TEXT_OUT 311
-#define REDWAX_TOOL_NO_TEXT_OUT 312
-#define REDWAX_TOOL_SSH_PRIVATE_OUT 313
-#define REDWAX_TOOL_SSH_PUBLIC_OUT 314
-#define REDWAX_TOOL_SMIMEA_OUT 315
-#define REDWAX_TOOL_SSHFP_OUT 316
-#define REDWAX_TOOL_TLSA_OUT 317
-#define REDWAX_TOOL_USER_IN 318
-#define REDWAX_TOOL_USER_OUT 319
-#define REDWAX_TOOL_GROUP_IN 320
-#define REDWAX_TOOL_GROUP_OUT 321
-#define REDWAX_TOOL_ORDER_OUT 322
-#define REDWAX_TOOL_DNS_SERVER 323
-#define REDWAX_TOOL_DNS_TRUST_ANCHOR 324
+#define REDWAX_TOOL_TLS_IN 262
+#define REDWAX_TOOL_FILTER 264
+#define REDWAX_TOOL_FILTER_EMAIL 265
+#define REDWAX_TOOL_FILTER_HOSTNAME 266
+#define REDWAX_TOOL_FILTER_IP 267
+#define REDWAX_TOOL_FILTER_CURRENT 268
+#define REDWAX_TOOL_FILTER_DATE 269
+#define REDWAX_TOOL_FILTER_EXPIRY 270
+#define REDWAX_TOOL_FILTER_DANE 271
+#define REDWAX_TOOL_FILTER_PURPOSE 272
+#define REDWAX_TOOL_FILTER_VERIFY_PARAM 273
+#define REDWAX_TOOL_FILTER_VERIFY_TLSA 274
+#define REDWAX_TOOL_FILTER_VERIFY_SMIMEA 275
+#define REDWAX_TOOL_CERT_OUT 276
+#define REDWAX_TOOL_NO_CERT_OUT 277
+#define REDWAX_TOOL_CHAIN_OUT 278
+#define REDWAX_TOOL_NO_CHAIN_OUT 279
+#define REDWAX_TOOL_ROOT_OUT 280
+#define REDWAX_TOOL_NO_ROOT_OUT 281
+#define REDWAX_TOOL_TRUST_OUT 282
+#define REDWAX_TOOL_NO_TRUST_OUT 283
+#define REDWAX_TOOL_CRL_OUT 284
+#define REDWAX_TOOL_NO_CRL_OUT 285
+#define REDWAX_TOOL_PARAM_OUT 286
+#define REDWAX_TOOL_NO_PARAM_OUT 287
+#define REDWAX_TOOL_KEY_IN 288
+#define REDWAX_TOOL_NO_KEY_IN 289
+#define REDWAX_TOOL_KEY_OUT 290
+#define REDWAX_TOOL_NO_KEY_OUT 291
+#define REDWAX_TOOL_AUTO_OUT 292
+#define REDWAX_TOOL_NO_AUTO_OUT 293
+#define REDWAX_TOOL_SECRET_SUFFIX_IN 294
+#define REDWAX_TOOL_SECRET_SUFFIX_OUT 295
+#define REDWAX_TOOL_SECRET_TOKEN_IN 296
+#define REDWAX_TOOL_SECRET_TOKEN_OUT 297
+#define REDWAX_TOOL_LABEL_OUT 298
+#define REDWAX_TOOL_NSS_OUT 299
+#define REDWAX_TOOL_NSS_SLOT_OUT 300
+#define REDWAX_TOOL_DER_OUT 301
+#define REDWAX_TOOL_PEM_OUT 302
+#define REDWAX_TOOL_PKCS12_OUT 303
+#define REDWAX_TOOL_PKCS11_OUT 304
+#define REDWAX_TOOL_PKCS11_MODULE_OUT 305
+#define REDWAX_TOOL_METADATA_OUT 306
+#define REDWAX_TOOL_METADATA_THRESHOLD 307
+#define REDWAX_TOOL_FORMAT_OUT 308
+#define REDWAX_TOOL_CALENDAR_OUT 309
+#define REDWAX_TOOL_CALENDAR_ALARM 310
+#define REDWAX_TOOL_REMINDER_OUT 311
+#define REDWAX_TOOL_JWKS_OUT 312
+#define REDWAX_TOOL_TEXT_OUT 313
+#define REDWAX_TOOL_NO_TEXT_OUT 314
+#define REDWAX_TOOL_SSH_PRIVATE_OUT 315
+#define REDWAX_TOOL_SSH_PUBLIC_OUT 316
+#define REDWAX_TOOL_SMIMEA_OUT 317
+#define REDWAX_TOOL_SSHFP_OUT 318
+#define REDWAX_TOOL_TLSA_OUT 319
+#define REDWAX_TOOL_USER_IN 320
+#define REDWAX_TOOL_USER_OUT 321
+#define REDWAX_TOOL_GROUP_IN 322
+#define REDWAX_TOOL_GROUP_OUT 323
+#define REDWAX_TOOL_ORDER_OUT 324
+#define REDWAX_TOOL_DNS_SERVER 325
+#define REDWAX_TOOL_DNS_TRUST_ANCHOR 326
 
 #define REDWAX_EXIT_OK 0
 #define REDWAX_EXIT_INIT 1
@@ -408,6 +415,9 @@
             "  --keychain-in=keychain\tRead certificates, intermediate certificates,\n"
             "\t\t\t\troot certificates, crls, and keys from a MacOS\n"
             "\t\t\t\tkeychain identified by the given name." },
+    { "tls-in", REDWAX_TOOL_TLS_IN, 1,
+            "  --tls-in=url\t\t\tRead certificates and intermediate certificates\n"
+            "\t\t\t\tfrom a TLS or DTLS endpoint at the given url." },
     { "filter", REDWAX_TOOL_FILTER, 1,
             "  --filter=type\t\t\tApply the given filter to pass inputs to the\n"
             "\t\t\t\toutputs. \"search\" will pass through all\n"
@@ -2675,6 +2685,14 @@
     return redwax_process(r, status, name);
 }
 
+static apr_status_t redwax_tls_in(redwax_tool_t *r, const char *arg, const char *name)
+{
+
+    apr_status_t status = rt_run_set_tls_in(r, arg);
+
+    return redwax_process(r, status, name);
+}
+
 void redwax_add_default_hooks(apr_pool_t *pool)
 {
     rt_hook_filter_poll(redwax_filter_poll, NULL, NULL, APR_HOOK_LAST);
@@ -2806,6 +2824,12 @@
         }
         case REDWAX_TOOL_KEYCHAIN_IN: {
             if (redwax_keychain_in(r, optarg, "keychain-in")) {
+                return r->rc;
+            }
+            break;
+        }
+        case REDWAX_TOOL_TLS_IN: {
+            if (redwax_tls_in(r, optarg, "tls-in")) {
                 return r->rc;
             }
             break;

Modified: redwax-tool/trunk/redwax-tool.h
==============================================================================
--- redwax-tool/trunk/redwax-tool.h	(original)
+++ redwax-tool/trunk/redwax-tool.h	Wed Apr  2 15:10:26 2025
@@ -26,9 +26,11 @@
 #include <apr_file_io.h>
 #include <apr_hash.h>
 #include <apr_hooks.h>
+#include <apr_network_io.h>
 #include <apr_poll.h>
 #include <apr_pools.h>
 #include <apr_tables.h>
+#include <apr_uri.h>
 
 #define REDWAX_DECLARE_MODULE(foo) \
     module foo##_module
@@ -167,6 +169,11 @@
     int dane_nxdomain;
     int dane_malformed;
     int dane_record;
+    int tls_bogus;
+    int tls_insecure;
+    int tls_nxdomain;
+    int tls_malformed;
+    int tls_record;
     int poll_work;
     int current;
     int cert_out;
@@ -356,6 +363,14 @@
 
 typedef apr_status_t(* redwax_dns_cb_t) (redwax_tool_t *r, redwax_dns_t *dns);
 
+typedef struct redwax_rdata_a_t {
+    apr_sockaddr_t *sockaddr;
+} redwax_rdata_a_t;
+
+typedef struct redwax_rdata_aaaa_t {
+    apr_sockaddr_t *sockaddr;
+} redwax_rdata_aaaa_t;
+
 typedef struct redwax_rdata_tlsa_t {
     const char *usage_name;
     const char *selector_name;
@@ -371,6 +386,8 @@
     unsigned char *data;
     int len;
     union {
+        redwax_rdata_a_t a;
+        redwax_rdata_a_t aaaa;
         redwax_rdata_tlsa_t tlsa;
     } rr;
 } redwax_rdata_t;
@@ -388,9 +405,18 @@
     int secure;
     int bogus;
     const char *why_bogus;
+    int port;
     redwax_dns_cb_t cb;
     void *ctx;
 } redwax_dns_t;
+
+typedef struct redwax_tls_t {
+    const char *unparsed_uri;
+    apr_uri_t uri;
+    int family;
+    int type;
+    int protocol;
+} redwax_tls_t;
 
 typedef apr_status_t(* redwax_pollfd_cb_t) (redwax_tool_t *r, void *ctx, apr_pollfd_t *descriptor);
 
@@ -580,6 +606,22 @@
         (redwax_tool_t *r, const char *arg))
 
 /**
+ * Hook to trigger a DNS lookup to read certificates from a TLS connection.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, set_tls_in,
+        (redwax_tool_t *r, const char *arg))
+
+/**
+ * Hook to read certificates from a DTLS connection.
+ *
+ * @param r The redwax-tool context.
+ */
+APR_DECLARE_EXTERNAL_HOOK(rt, REDWAX, apr_status_t, process_tls_in,
+        (redwax_tool_t *r, redwax_dns_t *dns))
+
+/**
  * Hook to complete incoming certificates / intermediates / keys
  * and pass filtered results to the outgoing certificates /
  * intermediates / keys.

Modified: redwax-tool/trunk/redwax-tool.spec.in
==============================================================================
--- redwax-tool/trunk/redwax-tool.spec.in	(original)
+++ redwax-tool/trunk/redwax-tool.spec.in	Wed Apr  2 15:10:26 2025
@@ -47,6 +47,16 @@
 %license COPYING
 
 %changelog
+* Thu Feb 27 2025 Graham Leggett <minfrin at sharp.fm> 0.9.9-1
+- Bugfix release
+* Thu Feb 27 2025 Graham Leggett <minfrin at sharp.fm> 0.9.8-1
+- Bugfix release
+* Thu Nov 28 2024 Graham Leggett <minfrin at sharp.fm> 0.9.7-1
+- Bugfix release
+* Mon Nov 11 2024 Graham Leggett <minfrin at sharp.fm> 0.9.6-1
+- Feature release
+* Mon Nov 11 2024 Graham Leggett <minfrin at sharp.fm> 0.9.5-1
+- Feature release
 * Thu Feb 08 2024 Graham Leggett <minfrin at sharp.fm> 0.9.4-1
 - Feature release
 * Sun Oct 15 2023 Graham Leggett <minfrin at sharp.fm> 0.9.3-1

Modified: redwax-tool/trunk/redwax_ldns.c
==============================================================================
--- redwax-tool/trunk/redwax_ldns.c	(original)
+++ redwax-tool/trunk/redwax_ldns.c	Wed Apr  2 15:10:26 2025
@@ -128,6 +128,8 @@
 {
     const unsigned char *der = cert->der;
 
+    /* ldns is tightly bound to openssl */
+
     X509 *x = d2i_X509(NULL, &der, cert->len);
 
     if (!x) {
@@ -178,6 +180,58 @@
 {
 
     switch (dns->rrtype) {
+    case LDNS_RR_TYPE_A: {
+
+        apr_sockaddr_t *new_sa = apr_pcalloc(r->pool, sizeof(apr_sockaddr_t));
+
+        new_sa->pool = r->pool;
+
+        new_sa->family = AF_INET;
+        new_sa->sa.sin.sin_family = AF_INET;
+
+        new_sa->sa.sin.sin_addr = *(struct in_addr *)rdata->data;
+
+        new_sa->hostname = apr_pstrdup(r->pool, dns->qname);
+
+        new_sa->salen = sizeof(struct sockaddr_in);
+        new_sa->addr_str_len = 16;
+        new_sa->ipaddr_ptr = &(new_sa->sa.sin.sin_addr);
+        new_sa->ipaddr_len = sizeof(struct in_addr);
+
+        new_sa->sa.sin.sin_port = htons(dns->port);
+        new_sa->port = dns->port;
+
+        rdata->rr.a.sockaddr = new_sa;
+
+        break;
+    }
+    case LDNS_RR_TYPE_AAAA: {
+
+        redwax_tls_t *tls = dns->ctx;
+
+        apr_sockaddr_t *new_sa = apr_pcalloc(r->pool, sizeof(apr_sockaddr_t));
+
+        new_sa->pool = r->pool;
+
+        new_sa->family = AF_INET6;
+        new_sa->sa.sin.sin_family = AF_INET6;
+
+        new_sa->sa.sin6.sin6_addr = *(struct in6_addr *)rdata->data;
+
+        new_sa->hostname = apr_pstrdup(r->pool, dns->qname);
+
+        new_sa->salen = sizeof(struct sockaddr_in6);
+        new_sa->addr_str_len = 46;
+        new_sa->ipaddr_ptr = &(new_sa->sa.sin6.sin6_addr);
+        new_sa->ipaddr_len = sizeof(struct in6_addr);
+
+        new_sa->sa.sin6.sin6_port = htons(dns->port);
+        new_sa->port = dns->port;
+
+        rdata->rr.aaaa.sockaddr = new_sa;
+
+        break;
+    }
     case LDNS_RR_TYPE_TLSA: {
 
         ldns_buffer buffer;

Modified: redwax-tool/trunk/redwax_openssl.c
==============================================================================
--- redwax-tool/trunk/redwax_openssl.c	(original)
+++ redwax-tool/trunk/redwax_openssl.c	Wed Apr  2 15:10:26 2025
@@ -22,6 +22,7 @@
 
 #include <apr_crypto.h>
 #include <apr_lib.h>
+#include <apr_portable.h>
 #include <apr_strings.h>
 
 #include "config.h"
@@ -72,6 +73,8 @@
 typedef struct {
     SSL_CTX *dane_ctx;
     SSL *dane_ssl;
+    apr_array_header_t *tls_hosts;
+    int tls_in_flight;
 } openssl_config_t;
 
 typedef struct {
@@ -82,6 +85,20 @@
 typedef struct {
     /* nothing yet */
 } openssl_key_config_t;
+
+typedef struct {
+    apr_pool_t *pool;
+    redwax_tls_t *tls;
+    const char *hostname;
+    apr_sockaddr_t *sockaddr;
+    apr_socket_t *socket;
+    apr_pollfd_t socket_read;
+    redwax_pollfd_t read_ctx;
+    apr_pollfd_t socket_write;
+    redwax_pollfd_t write_ctx;
+    SSL *ssl;
+    int do_shutdown;
+} openssl_tls_config_t;
 
 // move to config above
 static STACK_OF(X509) *cert_index;
@@ -1129,6 +1146,8 @@
     apr_pool_cleanup_register(r->pool, config->dane_ssl, cleanup_SSL,
             apr_pool_cleanup_null);
 
+    config->tls_hosts = apr_array_make(r->pool, 16, sizeof(openssl_tls_config_t *));
+
     cert_index = sk_X509_new_null();
     chain_index = sk_X509_new_null();
     trusted_index = sk_X509_new_null();
@@ -3743,6 +3762,490 @@
     }
 
     return APR_SUCCESS;
+}
+
+static apr_status_t tls_connect(redwax_tool_t *r);
+
+static apr_status_t cleanup_tls_in_flight(void *dummy)
+{
+    if (dummy) {
+        openssl_config_t *config = dummy;
+
+        config->tls_in_flight--;
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t tls_in_flight(redwax_tool_t *r, openssl_tls_config_t *tls_host)
+{
+    openssl_config_t *config = redwax_get_module_config(r->per_module, &openssl_module);
+
+    config->tls_in_flight++;
+
+    apr_pool_cleanup_register(tls_host->pool, config, cleanup_tls_in_flight,
+            apr_pool_cleanup_null);
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t redwax_openssl_handshake_cb(redwax_tool_t *r, openssl_tls_config_t *tls_host)
+{
+    apr_status_t status = APR_SUCCESS;
+
+    int rv, label_len;
+
+    redwax_tls_t *tls = tls_host->tls;
+
+    rv = SSL_do_handshake(tls_host->ssl);
+
+    if (1 == rv || 2 == rv) {
+
+        STACK_OF(X509) *sk;
+
+        int i;
+
+        /* negotiated connection took place */
+
+        sk = SSL_get_peer_cert_chain(tls_host->ssl);
+
+        for (i = 0; i < sk_X509_num(sk); i++) {
+
+            unsigned char *der = NULL;
+            const char *label;
+
+            redwax_certificate_t *cert;
+
+            X509 *x = sk_X509_value(sk, i);
+
+            if (!x) {
+                redwax_print_error(r, "tls-in: could not read certificate from %pI (%s), skipping.\n",
+                        tls_host->sockaddr, tls->unparsed_uri);
+                redwax_openssl_print_errors(r);
+                continue;
+            }
+
+            if (X509_check_ca(x)) {
+
+                cert = apr_array_push(r->intermediates_in);
+
+                apr_pool_create(&cert->pool, r->pool);
+
+                cert->common.type = REDWAX_CERTIFICATE_X509;
+                cert->common.category = REDWAX_CERTIFICATE_INTERMEDIATE;
+
+                redwax_print_error(r, "tls-in: intermediate: %s\n",
+                        redwax_openssl_name(cert->pool,
+                                X509_get_subject_name(x)));
+            }
+            else {
+
+                cert = apr_array_push(r->certs_in);
+
+                apr_pool_create(&cert->pool, r->pool);
+
+                cert->common.type = REDWAX_CERTIFICATE_X509;
+                cert->common.category = REDWAX_CERTIFICATE_END_ENTITY;
+
+                redwax_print_error(r, "tls-in: certificate: %s\n",
+                        redwax_openssl_name(cert->pool,
+                                X509_get_subject_name(x)));
+
+            }
+
+            cert->per_module = redwax_create_module_config(cert->pool);
+
+            label = (const char *)X509_alias_get0(x, &label_len);
+            cert->label = apr_pstrndup(cert->pool, label, label_len);
+            cert->label_len = label_len;
+
+            cert->len = i2d_X509(x, &der);
+            cert->der = der;
+
+            apr_pool_cleanup_register(cert->pool, der, cleanup_alloc,
+                    apr_pool_cleanup_null);
+
+            cert->origin = apr_pstrdup(cert->pool, tls_host->hostname);
+
+            rt_run_normalise_certificate(r, cert, 1);
+
+        }
+
+        tls_host->do_shutdown = 1;
+
+        status = apr_pollcb_add(r->poll, &tls_host->socket_write);
+
+        if (APR_SUCCESS != status) {
+            redwax_print_error(r,
+                    "tls-in: could not add write descriptor to poll: %pm\n", &status);
+            return status;
+        }
+
+        /* req writecb work */
+        r->poll_work++;
+
+    }
+    else {
+        switch (SSL_get_error(tls_host->ssl, rv)) {
+        case SSL_ERROR_WANT_WRITE: {
+
+            status = apr_pollcb_add(r->poll, &tls_host->socket_write);
+
+            if (APR_SUCCESS != status) {
+                redwax_print_error(r,
+                        "tls-in: could not add write descriptor to poll: %pm\n", &status);
+                return status;
+            }
+
+            /* req writecb work */
+            r->poll_work++;
+
+            break;
+        }
+        case SSL_ERROR_WANT_ASYNC: {
+
+            redwax_print_error(r,
+                    "tls-in: unexpected SSL_ERROR_WANT_ASYNC in the bagging area\n");
+            return APR_EGENERAL;
+        }
+        case SSL_ERROR_WANT_READ: {
+
+            status = apr_pollcb_add(r->poll, &tls_host->socket_read);
+
+            if (APR_SUCCESS != status) {
+                redwax_print_error(r,
+                        "tls-in: could not add read descriptor to poll: %pm\n", &status);
+                return status;
+            }
+
+            /* req writecb work */
+            r->poll_work++;
+
+            break;
+        }
+        default:
+
+            redwax_print_error(r,
+                    "tls-in: TLS handshake of '%s' connection to %pI failed, ingoring.\n",
+                    tls->unparsed_uri, tls_host->sockaddr);
+            redwax_openssl_print_errors(r);
+
+            return APR_SUCCESS;
+        }
+    }
+
+    return status;
+}
+
+static apr_status_t redwax_openssl_shutdown_cb(redwax_tool_t *r, openssl_tls_config_t *tls_host)
+{
+    apr_status_t status = APR_SUCCESS;
+
+    int rv;
+
+    rv = SSL_shutdown(tls_host->ssl);
+
+    if (0 == rv) {
+
+        /* not yet done, wait for the response */
+        status = apr_pollcb_add(r->poll, &tls_host->socket_read);
+
+        if (APR_SUCCESS != status) {
+            redwax_print_error(r,
+                    "tls-in: could not add read descriptor to poll: %pm\n", &status);
+            return status;
+        }
+
+        /* req writecb work */
+        r->poll_work++;
+
+    }
+    else if (1 == rv) {
+
+        /* we're done */
+        apr_pool_destroy(tls_host->pool);
+
+        /* line up the next connection(s) */
+        return tls_connect(r);
+    }
+    else {
+
+        redwax_tls_t *tls = tls_host->tls;
+
+        switch (SSL_get_error(tls_host->ssl, rv)) {
+        case SSL_ERROR_WANT_WRITE: {
+
+            status = apr_pollcb_add(r->poll, &tls_host->socket_write);
+
+            if (APR_SUCCESS != status) {
+                redwax_print_error(r,
+                        "tls-in: could not add write descriptor to poll: %pm\n", &status);
+                return status;
+            }
+
+            /* req writecb work */
+            r->poll_work++;
+
+            break;
+        }
+        case SSL_ERROR_WANT_ASYNC: {
+
+            redwax_print_error(r,
+                    "tls-in: unexpected SSL_ERROR_WANT_ASYNC in the bagging area\n");
+            return APR_EGENERAL;
+        }
+        case SSL_ERROR_WANT_READ: {
+
+            status = apr_pollcb_add(r->poll, &tls_host->socket_read);
+
+            if (APR_SUCCESS != status) {
+                redwax_print_error(r,
+                        "tls-in: could not add read descriptor to poll: %pm\n", &status);
+                return status;
+            }
+
+            /* req writecb work */
+            r->poll_work++;
+
+            break;
+        }
+        default:
+
+            redwax_print_error(r,
+                    "tls-in: shutdown of '%s' connection to %pI failed, ingoring.\n",
+                    tls->unparsed_uri, tls_host->sockaddr);
+            redwax_openssl_print_errors(r);
+
+            return APR_SUCCESS;
+        }
+    }
+
+    return status;
+}
+
+static apr_status_t redwax_openssl_filter_read_cb(redwax_tool_t *r, void *baton, apr_pollfd_t *descriptor)
+{
+
+    redwax_pollfd_t *read_ctx = descriptor->client_data;
+    openssl_tls_config_t *tls_host = read_ctx->ctx;
+
+    /* ack readcb work */
+    r->poll_work--;
+
+    if (tls_host->do_shutdown) {
+        return redwax_openssl_shutdown_cb(r, tls_host);
+    }
+
+    return redwax_openssl_handshake_cb(r, tls_host);
+}
+
+static apr_status_t redwax_openssl_filter_write_cb(redwax_tool_t *r, void *baton, apr_pollfd_t *descriptor)
+{
+
+    redwax_pollfd_t *write_ctx = descriptor->client_data;
+    openssl_tls_config_t *tls_host = write_ctx->ctx;
+    redwax_tls_t *tls = tls_host->tls;
+
+    apr_status_t status = APR_SUCCESS;
+
+    /* ack readcb work */
+    r->poll_work--;
+
+    if (!tls_host->ssl) {
+
+        SSL_CTX *ctx;
+
+        apr_os_sock_t fd;
+
+        status = apr_os_sock_get(&fd, tls_host->socket);
+
+        if (APR_SUCCESS != status) {
+            redwax_print_error(r,
+                    "tls-in: could not convert SSL fd: %pm\n", &status);
+            return status;
+        }
+
+        if (tls->protocol == APR_PROTO_TCP) {
+            ctx = SSL_CTX_new(TLS_client_method());
+        }
+        else {
+            ctx = SSL_CTX_new(DTLS_client_method());
+        }
+
+        apr_pool_cleanup_register(tls_host->pool, ctx, cleanup_SSL_CTX,
+                apr_pool_cleanup_null);
+
+        tls_host->ssl = SSL_new(ctx);
+
+        apr_pool_cleanup_register(tls_host->pool, tls_host->ssl, cleanup_SSL,
+                apr_pool_cleanup_null);
+
+        SSL_set_connect_state(tls_host->ssl);
+
+        SSL_set_verify(tls_host->ssl, SSL_VERIFY_NONE, NULL);
+
+        if (SSL_set_fd(tls_host->ssl, fd) <= 0) {
+            redwax_openssl_print_errors(r);
+            return APR_EGENERAL;
+        }
+
+        if (SSL_set1_host(tls_host->ssl, tls_host->hostname) <= 0) {
+            redwax_openssl_print_errors(r);
+            return APR_EGENERAL;
+        }
+
+        if (SSL_set_tlsext_host_name(tls_host->ssl, tls_host->hostname) <= 0) {
+            redwax_openssl_print_errors(r);
+            return APR_EGENERAL;
+        }
+
+        /* todo: SSL_set_alpn_protos */
+    }
+
+    if (tls_host->do_shutdown) {
+        return redwax_openssl_shutdown_cb(r, tls_host);
+    }
+
+    return redwax_openssl_handshake_cb(r, tls_host);
+}
+
+static apr_status_t tls_connect(redwax_tool_t *r)
+{
+    openssl_config_t *config = redwax_get_module_config(r->per_module, &openssl_module);
+
+    apr_status_t status;
+
+    while (config->tls_hosts->nelts && config->tls_in_flight < 2) {
+
+        openssl_tls_config_t **ts = apr_array_pop(config->tls_hosts);
+        openssl_tls_config_t *tls_host = *ts;
+
+        tls_in_flight(r, tls_host);
+
+        status = apr_socket_create(&tls_host->socket, tls_host->sockaddr->family, SOCK_STREAM, APR_PROTO_TCP,
+                tls_host->pool);
+
+        status = apr_socket_connect(tls_host->socket, tls_host->sockaddr);
+
+        status = apr_socket_opt_set(tls_host->socket, APR_SO_NONBLOCK, 1);
+
+        /* set up the read callback */
+        tls_host->read_ctx.cb = redwax_openssl_filter_read_cb;
+        tls_host->read_ctx.ctx = tls_host;
+
+        /* set up read descriptor */
+        tls_host->socket_read.desc_type = APR_POLL_SOCKET;
+        tls_host->socket_read.reqevents = APR_POLLIN;
+        tls_host->socket_read.desc.s = tls_host->socket;
+        tls_host->socket_read.client_data = &tls_host->read_ctx;
+
+        /* set up the write callback */
+        tls_host->write_ctx.cb = redwax_openssl_filter_write_cb;
+        tls_host->write_ctx.ctx = tls_host;
+
+        /* set up write descriptor */
+        tls_host->socket_write.desc_type = APR_POLL_SOCKET;
+        tls_host->socket_write.reqevents = APR_POLLOUT;
+        tls_host->socket_write.desc.s = tls_host->socket;
+        tls_host->socket_write.client_data = &tls_host->write_ctx;
+
+        status = apr_pollcb_add(r->poll, &tls_host->socket_write);
+
+        if (APR_SUCCESS != status) {
+            redwax_print_error(r,
+                    "tls-in: could not add write descriptor to poll: %pm\n", &status);
+            return status;
+        }
+
+        /* req writecb work */
+        r->poll_work++;
+
+    }
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t redwax_openssl_process_tls_in(redwax_tool_t *r, redwax_dns_t *dns)
+{
+    openssl_config_t *config = redwax_get_module_config(r->per_module, &openssl_module);
+
+    if (dns->bogus) {
+
+        redwax_print_error(r,
+                "tls-in: DNS response for '%s' failed "
+                "DNSSEC validation, ignoring: %s.\n", dns->qname, dns->why_bogus);
+
+        r->tls_bogus++;
+
+        return APR_SUCCESS;
+    }
+
+    if (!dns->secure) {
+
+        redwax_print_error(r,
+                "tls-in: warning: DNS response for '%s' is "
+                "not DNSSEC secured.\n", dns->qname);
+
+        r->tls_insecure++;
+    }
+
+    if (dns->nxdomain) {
+
+        redwax_print_error(r,
+                "tls-in: DNS record for '%s' does "
+                "not exist, ignoring.\n", dns->qname);
+
+        r->tls_nxdomain++;
+
+        return APR_SUCCESS;
+    }
+
+    if (dns->rdata) {
+
+        int i;
+
+        redwax_tls_t *tls = dns->ctx;
+
+        for (i = 0; i < dns->rdata->nelts; i++)
+        {
+            apr_pool_t *pool;
+            openssl_tls_config_t *tls_host;
+
+            const redwax_rdata_t *rdata = &APR_ARRAY_IDX(dns->rdata, i,
+                    const redwax_rdata_t);
+
+            openssl_tls_config_t **ts = apr_array_push(config->tls_hosts);
+
+            apr_pool_create(&pool, r->pool);
+
+            *ts = tls_host = apr_pcalloc(pool, sizeof(openssl_tls_config_t));
+
+            tls_host->pool = pool;
+
+            switch (dns->rrtype) {
+            case 1:
+                tls_host->sockaddr = rdata->rr.a.sockaddr;
+                tls_host->hostname = dns->qname;
+                break;
+            case 28:
+                tls_host->sockaddr = rdata->rr.aaaa.sockaddr;
+                tls_host->hostname = dns->qname;
+                break;
+            default:
+                return APR_EINVAL;
+            }
+
+            tls_host->tls = tls;
+
+            redwax_print_error(r,
+                    "tls-in: DNS record for '%s' maps to %pI.\n",
+                    tls->unparsed_uri, tls_host->sockaddr);
+
+        }
+
+    }
+
+    return tls_connect(r);
 }
 
 static apr_status_t redwax_openssl_process_pkcs12_out(redwax_tool_t *r,
@@ -6398,6 +6901,7 @@
     rt_hook_process_pem_in(redwax_openssl_process_pem_in, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_process_trust_pem_in(redwax_openssl_process_trust_pem_in, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_process_pkcs12_in(redwax_openssl_process_pkcs12_in, NULL, NULL, APR_HOOK_MIDDLE);
+    rt_hook_process_tls_in(redwax_openssl_process_tls_in, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_set_tlsa(redwax_openssl_set_tlsa, NULL, NULL, APR_HOOK_LAST);
     rt_hook_process_tlsa(redwax_openssl_process_tlsa, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_complete_filter(redwax_openssl_complete_filter_verify, NULL, NULL, APR_HOOK_MIDDLE);

Modified: redwax-tool/trunk/redwax_unbound.c
==============================================================================
--- redwax-tool/trunk/redwax_unbound.c	(original)
+++ redwax-tool/trunk/redwax_unbound.c	Wed Apr  2 15:10:26 2025
@@ -41,12 +41,9 @@
 
 typedef struct {
     struct ub_ctx *ctx;
-    apr_pollfd_t socket_read;
-    redwax_pollfd_t read_ctx;
-    apr_pollfd_t socket_write;
-    redwax_pollfd_t write_ctx;
+    apr_pollfd_t socket_poll;
+    redwax_pollfd_t poll_ctx;
     apr_status_t status;
-    int socket_read_work;
     int dns_work;
     int dns_server_set;
     int dns_trust_anchor_set;
@@ -162,6 +159,7 @@
             dns->rrtype = 52 /* TYPE TLSA */;
             dns->rrclass = 1 /* CLASS IN (internet) */;
             dns->cb = rt_run_process_tlsa;
+            dns->port = uri.port;
 
             qname = apr_array_push(r->tlsa_qnames);
             *qname = tlsa;
@@ -201,6 +199,7 @@
                 dns->rrtype = 52 /* TYPE TLSA */;
                 dns->rrclass = 1 /* CLASS IN (internet) */;
                 dns->cb = rt_run_process_tlsa;
+                dns->port = uri.port ? uri.port : ntohs(ent->s_port);
 
                 qname = apr_array_push(r->tlsa_qnames);
                 *qname = tlsa;
@@ -237,6 +236,164 @@
     return APR_ENOTIMPL;
 }
 
+static apr_status_t redwax_unbound_set_tls_in(redwax_tool_t *r, const char *arg)
+{
+    apr_uri_t uri;
+
+    apr_status_t status;
+
+    int protocol = 0;
+    int type = 0;
+
+    status = apr_uri_parse(r->pool, arg, &uri);
+    if (APR_SUCCESS != status) {
+        redwax_print_error(r,
+                "Could not parse URI '%s': %pm\n", arg, &status);
+        return status;
+    }
+
+    if (!uri.hostname) {
+        redwax_print_error(r,
+                "URI '%s': hostname missing\n", arg);
+        return APR_EINVAL;
+    }
+
+    /* fixme: Use inet_pton to detect raw IP/IPv6 addresses and skip lookup */
+
+    if (!strcmp(uri.scheme, "tcp")) {
+        protocol = APR_PROTO_TCP;
+        type = SOCK_STREAM;
+    }
+    else if (!strcmp(uri.scheme, "udp")) {
+        protocol = APR_PROTO_UDP;
+        type = SOCK_DGRAM;
+    }
+    else if (!strcmp(uri.scheme, "sctp")) {
+        protocol = APR_PROTO_SCTP;
+        type= SOCK_SEQPACKET;
+    }
+
+    if (protocol) {
+
+        if (uri.port) {
+
+            redwax_dns_t *dns;
+            redwax_tls_t *tls;
+
+            tls = apr_palloc(r->pool, sizeof(redwax_tls_t));
+
+            tls->unparsed_uri = arg;
+            tls->uri = uri;
+            tls->protocol = protocol;
+            tls->type = type;
+
+            dns = apr_array_push(r->dns_requests);
+
+            dns->r = r;
+            dns->basename = uri.hostname;
+            dns->qname = uri.hostname;
+            dns->rrtype = 28 /* TYPE AAAA */;
+            dns->rrclass = 1 /* CLASS IN (internet) */;
+            dns->cb = rt_run_process_tls_in;
+            dns->ctx = tls;
+            dns->port = uri.port;
+
+            dns = apr_array_push(r->dns_requests);
+
+            dns->r = r;
+            dns->basename = uri.hostname;
+            dns->qname = uri.hostname;
+            dns->rrtype = 1 /* TYPE A */;
+            dns->rrclass = 1 /* CLASS IN (internet) */;
+            dns->cb = rt_run_process_tls_in;
+            dns->ctx = tls;
+            dns->port = uri.port;
+
+            return APR_SUCCESS;
+        }
+        else {
+            redwax_print_error(r,
+                    "URI '%s': port missing\n", arg);
+            return APR_EINVAL;
+        }
+    }
+
+    else if (uri.scheme) {
+
+        int found = 0;
+
+        setservent(1);
+
+        struct servent *ent;
+
+        while ((ent = getservent())) {
+
+            if (!strcmp(uri.scheme, ent->s_name)) {
+
+                redwax_dns_t *dns;
+                redwax_tls_t *tls;
+
+                tls = apr_palloc(r->pool, sizeof(redwax_tls_t));
+
+                /* we hard code the protocol to TCP, as the services
+                 * file contacts lots of bogus tcp/udp entries.
+                 */
+
+                tls->unparsed_uri = arg;
+                tls->uri = uri;
+                tls->protocol = APR_PROTO_TCP;
+                tls->type = SOCK_STREAM;
+
+                dns = apr_array_push(r->dns_requests);
+
+                dns->r = r;
+                dns->basename = uri.hostname;
+                dns->qname = uri.hostname;
+                dns->rrtype = 28 /* TYPE AAAA */;
+                dns->rrclass = 1 /* CLASS IN (internet) */;
+                dns->cb = rt_run_process_tls_in;
+                dns->ctx = tls;
+                dns->port = uri.port ? uri.port : ntohs(ent->s_port);
+
+                dns = apr_array_push(r->dns_requests);
+
+                dns->r = r;
+                dns->basename = uri.hostname;
+                dns->qname = uri.hostname;
+                dns->rrtype = 1 /* TYPE A */;
+                dns->rrclass = 1 /* CLASS IN (internet) */;
+                dns->cb = rt_run_process_tls_in;
+                dns->ctx = tls;
+                dns->port = uri.port ? uri.port : ntohs(ent->s_port);
+
+                found = 1;
+
+                break;
+            }
+
+        }
+
+        endservent();
+
+        if (!found) {
+            redwax_print_error(r,
+                    "URI '%s': protocol '%s' not found\n", arg, uri.scheme);
+            return APR_EINVAL;
+        }
+        else {
+            return APR_SUCCESS;
+        }
+
+    }
+
+    else {
+        redwax_print_error(r,
+                "URI '%s': scheme missing\n", arg);
+        return APR_EINVAL;
+    }
+
+}
+
 static apr_status_t redwax_unbound_filter_read_cb(redwax_tool_t *r, void *baton, apr_pollfd_t *descriptor)
 {
     unbound_config_t *config = redwax_get_module_config(r->per_module, &unbound_module);
@@ -246,9 +403,6 @@
 
     /* ack readcb work */
     r->poll_work--;
-
-    /* ack socket read work */
-    config->socket_read_work--;
 
     rv = ub_process(config->ctx);
 
@@ -265,19 +419,17 @@
 
     if (config->dns_work) {
 
-        status = apr_pollcb_add(r->poll, &config->socket_read);
+        /* line up next event */
+        status = apr_pollcb_add(r->poll, &config->socket_poll);
 
         if (APR_SUCCESS != status) {
             redwax_print_error(r,
-                    "Could not add read descriptor to poll: %pm\n", &status);
+                    "unbound: could not add descriptor to poll: %pm\n", &status);
             return status;
         }
 
         /* req readcb work */
         r->poll_work++;
-
-        /* req socket read work */
-        config->socket_read_work++;
     }
 
     return status;
@@ -361,40 +513,42 @@
     /* req dns lookup work */
     config->dns_work++;
 
-    if (!config->socket_read_work) {
-
-        status = apr_pollcb_add(r->poll, &config->socket_read);
-
-        if (APR_SUCCESS != status) {
-            redwax_print_error(r,
-                    "Could not add read descriptor to poll: %pm\n", &status);
-            return status;
-        }
-
-        /* req readcb work */
-        r->poll_work++;
-
-        /* req socket read work */
-        config->socket_read_work++;
-
-    }
-
-    if (r->dns_requests->nelts) {
-
-        status = apr_pollcb_add(r->poll, &config->socket_write);
-
-        if (APR_SUCCESS != status) {
-            redwax_print_error(r,
-                    "Could not add write descriptor to poll: %pm\n", &status);
-            return status;
-        }
-
-        /* req writecb work */
-        r->poll_work++;
-
-    }
+    /* we are done sending requests, poll for responses only */
+    if (!r->dns_requests->nelts) {
+        config->socket_poll.reqevents = APR_POLLIN;
+    }
+
+    /* line up next event */
+    status = apr_pollcb_add(r->poll, &config->socket_poll);
+
+    if (APR_SUCCESS != status) {
+        redwax_print_error(r,
+                "Could not add read descriptor to poll: %pm\n", &status);
+        return status;
+    }
+
+    /* req readcb work */
+    r->poll_work++;
 
     return status;
+}
+
+static apr_status_t redwax_unbound_filter_cb(redwax_tool_t *r, void *baton, apr_pollfd_t *descriptor)
+{
+    if (descriptor->rtnevents & APR_POLLIN) {
+        /* process reads first if available to relieve pressure */
+        return redwax_unbound_filter_read_cb(r, baton, descriptor);
+    }
+    else if (descriptor->rtnevents & APR_POLLOUT) {
+        /* do writes if needed */
+        return redwax_unbound_filter_write_cb(r, baton, descriptor);
+    }
+    else {
+        /* errors are handled by ub_process() */
+        return redwax_unbound_filter_read_cb(r, baton, descriptor);
+    }
+
+    return APR_SUCCESS;
 }
 
 static apr_status_t redwax_unbound_filter_poll(redwax_tool_t *r)
@@ -458,25 +612,17 @@
         return status;
     }
 
-    /* set up the read callback */
-    config->read_ctx.cb = redwax_unbound_filter_read_cb;
-
-    /* set up read descriptor */
-    config->socket_read.desc_type = APR_POLL_SOCKET;
-    config->socket_read.reqevents = APR_POLLIN;
-    config->socket_read.desc.s = s;
-    config->socket_read.client_data = &config->read_ctx;
-
-    /* set up the write callback */
-    config->write_ctx.cb = redwax_unbound_filter_write_cb;
-
-    /* set up write descriptor */
-    config->socket_write.desc_type = APR_POLL_SOCKET;
-    config->socket_write.reqevents = APR_POLLOUT;
-    config->socket_write.desc.s = s;
-    config->socket_write.client_data = &config->write_ctx;
-
-    status = apr_pollcb_add(r->poll, &config->socket_write);
+    /* set up the read/write callback */
+
+    config->poll_ctx.cb = redwax_unbound_filter_cb;
+
+    /* set up read/write descriptor */
+    config->socket_poll.desc_type = APR_POLL_SOCKET;
+    config->socket_poll.reqevents = APR_POLLIN | APR_POLLOUT;
+    config->socket_poll.desc.s = s;
+    config->socket_poll.client_data = &config->poll_ctx;
+
+    status = apr_pollcb_add(r->poll, &config->socket_poll);
 
     if (APR_SUCCESS != status) {
         redwax_print_error(r,
@@ -497,6 +643,7 @@
     rt_hook_set_dns_trust_anchor(redwax_unbound_set_dns_trust_anchor, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_set_tlsa(redwax_unbound_set_tlsa, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_set_smimea(redwax_unbound_set_smimea, NULL, NULL, APR_HOOK_MIDDLE);
+    rt_hook_set_tls_in(redwax_unbound_set_tls_in, NULL, NULL, APR_HOOK_MIDDLE);
     rt_hook_filter_poll(redwax_unbound_filter_poll, NULL, NULL, APR_HOOK_MIDDLE);
 }
 



More information about the rt-commit mailing list