+ return rbl_context_new();
+ }
+}
+
+static void rbl_context_release(rbl_context_t *context)
+{
+ rbl_context_wipe(context);
+ array_add(ctx_pool, context);
+}
+
+static void rbl_exit(void)
+{
+ if (ctx != NULL) {
+ ub_ctx_delete(ctx);
+ ctx = NULL;
+ }
+ if (async_event != NULL) {
+ client_release(async_event);
+ async_event = NULL;
+ }
+ array_deep_wipe(ctx_pool, rbl_context_delete);
+}
+module_exit(rbl_exit);
+
+static void rbl_callback(void *arg, int err, struct ub_result *result)
+{
+ rbl_context_t *context = arg;
+ if (err != 0) {
+ debug("asynchronous request led to an error");
+ *context->result = RBL_ERROR;
+ } else if (result->nxdomain) {
+ debug("asynchronous request done, %s NOT FOUND", result->qname);
+ *context->result = RBL_NOTFOUND;
+ } else {
+ debug("asynchronous request done, %s FOUND", result->qname);
+ *context->result = RBL_FOUND;
+ }
+ if (context->call != NULL) {
+ context->call(context->result, context->data);
+ }
+ ub_resolve_free(result);
+ rbl_context_release(context);
+}
+
+static int rbl_handler(client_t *event, void *config)
+{
+ int retval = 0;
+ debug("rbl_handler called: ub_fd triggered");
+ client_io_none(event);
+ if ((retval = ub_process(ctx)) != 0) {
+ err("error in DNS resolution: %s", ub_strerror(retval));
+ }
+ client_io_ro(event);
+ return 0;
+}
+
+static inline bool rbl_dns_check(const char *hostname, rbl_result_t *result,
+ rbl_result_callback_t callback, void *data)
+{
+ if (ctx == NULL) {
+ ctx = ub_ctx_create();
+ ub_ctx_async(ctx, true);
+ if ((async_event = client_register(ub_fd(ctx), rbl_handler, NULL)) == NULL) {
+ crit("cannot register asynchronous DNS event handler");
+ abort();