1 /******************************************************************************/
2 /* pfixtools: a collection of postfix related tools */
4 /* ________________________________________________________________________ */
6 /* Redistribution and use in source and binary forms, with or without */
7 /* modification, are permitted provided that the following conditions */
10 /* 1. Redistributions of source code must retain the above copyright */
11 /* notice, this list of conditions and the following disclaimer. */
12 /* 2. Redistributions in binary form must reproduce the above copyright */
13 /* notice, this list of conditions and the following disclaimer in the */
14 /* documentation and/or other materials provided with the distribution. */
15 /* 3. The names of its contributors may not be used to endorse or promote */
16 /* products derived from this software without specific prior written */
19 /* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS */
20 /* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY */
23 /* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL */
24 /* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS */
25 /* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) */
26 /* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, */
27 /* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */
28 /* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
29 /* POSSIBILITY OF SUCH DAMAGE. */
31 /* Copyright (c) 2006-2008 the Authors */
32 /* see AUTHORS and source files for details */
33 /******************************************************************************/
36 * Copyright © 2008 Florent Bruneau
46 typedef struct rbl_context_t {
48 rbl_result_callback_t call;
53 static struct ub_ctx *ctx = NULL;
54 static client_t *async_event = NULL;
55 static PA(rbl_context_t) ctx_pool = ARRAY_INIT;
57 static rbl_context_t *rbl_context_new(void)
59 return p_new(rbl_context_t, 1);
62 static void rbl_context_delete(rbl_context_t **context)
69 static void rbl_context_wipe(rbl_context_t *context)
74 static rbl_context_t *rbl_context_acquire(void)
76 if (array_len(ctx_pool) > 0) {
77 return array_pop_last(ctx_pool);
79 return rbl_context_new();
83 static void rbl_context_release(rbl_context_t *context)
85 rbl_context_wipe(context);
86 array_add(ctx_pool, context);
89 static void rbl_exit(void)
95 if (async_event != NULL) {
96 client_release(async_event);
99 array_deep_wipe(ctx_pool, rbl_context_delete);
101 module_exit(rbl_exit);
103 static void rbl_callback(void *arg, int err, struct ub_result *result)
105 rbl_context_t *context = arg;
107 debug("asynchronous request led to an error");
108 *context->result = RBL_ERROR;
109 } else if (result->nxdomain) {
110 debug("asynchronous request done, %s NOT FOUND", result->qname);
111 *context->result = RBL_NOTFOUND;
113 debug("asynchronous request done, %s FOUND", result->qname);
114 *context->result = RBL_FOUND;
116 if (context->call != NULL) {
117 context->call(context->result, context->data);
119 ub_resolve_free(result);
120 rbl_context_release(context);
123 static int rbl_handler(client_t *event, void *config)
126 debug("rbl_handler called: ub_fd triggered");
127 client_io_none(event);
128 if ((retval = ub_process(ctx)) != 0) {
129 err("error in DNS resolution: %s", ub_strerror(retval));
135 static inline bool rbl_dns_check(const char *hostname, rbl_result_t *result,
136 rbl_result_callback_t callback, void *data)
139 ctx = ub_ctx_create();
140 ub_ctx_async(ctx, true);
141 if ((async_event = client_register(ub_fd(ctx), rbl_handler, NULL)) == NULL) {
142 crit("cannot register asynchronous DNS event handler");
146 rbl_context_t *context = rbl_context_acquire();
147 context->result = result;
148 context->call = callback;
149 context->data = data;
150 debug("running dns resolution on %s", hostname);
151 if (ub_resolve_async(ctx, (char*)hostname, 1, 1, context, rbl_callback, NULL) == 0) {
156 rbl_context_release(context);
161 bool rbl_check(const char *rbl, uint32_t ip, rbl_result_t *result,
162 rbl_result_callback_t callback, void *data)
167 len = snprintf(host, 257, "%d.%d.%d.%d.%s.",
168 ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff,
170 if (len >= (int)sizeof(host))
172 if (host[len - 2] == '.')
173 host[len - 1] = '\0';
174 return rbl_dns_check(host, result, callback, data);
177 bool rhbl_check(const char *rhbl, const char *hostname, rbl_result_t *result,
178 rbl_result_callback_t callback, void *data)
183 len = snprintf(host, 257, "%s.%s.", hostname, rhbl);
184 if (len >= (int)sizeof(host))
186 if (host[len - 2] == '.')
187 host[len - 1] = '\0';
188 return rbl_dns_check(host, result, callback, data);