66 #include <sys/socket.h>
67 #include <netinet/in.h>
68 #include <arpa/inet.h>
99 static char *psc_dnsbl_service;
114 static HTABLE *dnsbl_site_cache;
143 static HTABLE *dnsbl_score_cache;
146 void (*callback) (
int,
void *);
165 #define PSC_CALL_BACK_INIT(sp) do { \
170 #define PSC_CALL_BACK_INDEX_OF_LAST(sp) ((sp)->index - 1)
172 #define PSC_CALL_BACK_CANCEL(sp, idx) do { \
173 PSC_CALL_BACK_ENTRY *_cb_; \
174 if ((idx) < 0 || (idx) >= (sp)->index) \
175 msg_panic("%s: index %d must be >= 0 and < %d", \
176 myname, (idx), (sp)->index); \
177 _cb_ = (sp)->table + (idx); \
178 event_cancel_timer(_cb_->callback, _cb_->context); \
179 _cb_->callback = 0; \
183 #define PSC_CALL_BACK_EXTEND(hp, sp) do { \
184 if ((sp)->index >= (sp)->limit) { \
185 int _count_ = ((sp)->limit ? (sp)->limit * 2 : 5); \
186 (hp)->value = myrealloc((void *) (sp), sizeof(*(sp)) + \
187 _count_ * sizeof((sp)->table)); \
188 (sp) = (PSC_DNSBL_SCORE *) (hp)->value; \
189 (sp)->limit = _count_; \
193 #define PSC_CALL_BACK_ENTER(sp, fn, ctx) do { \
194 PSC_CALL_BACK_ENTRY *_cb_ = (sp)->table + (sp)->index++; \
195 _cb_->callback = (fn); \
196 _cb_->context = (ctx); \
199 #define PSC_CALL_BACK_NOTIFY(sp, ev) do { \
200 PSC_CALL_BACK_ENTRY *_cb_; \
201 for (_cb_ = (sp)->table; _cb_ < (sp)->table + (sp)->index; _cb_++) \
202 if (_cb_->callback != 0) \
203 _cb_->callback((ev), _cb_->context); \
206 #define PSC_NULL_EVENT (0)
221 static void psc_dnsbl_add_site(
const char *site)
223 const char *myname =
"psc_dnsbl_add_site";
229 const char *weight_text;
242 if ((weight_text =
split_at(saved_site,
'*')) != 0) {
243 if (sscanf(weight_text,
"%d%c", &weight, &junk) != 1)
244 msg_fatal(
"bad DNSBL weight factor \"%s\" in \"%s\"",
250 if ((pattern_text =
split_at(saved_site,
'=')) != 0) {
253 msg_fatal(
"bad DNSBL filter syntax: %s", parse_err);
256 msg_fatal(
"bad DNSBL domain name \"%s\" in \"%s\"",
260 msg_info(
"%s: \"%s\" -> domain=\"%s\" pattern=\"%s\" weight=%d",
261 myname, site, saved_site, pattern_text ? pattern_text :
271 ht =
htable_enter(dnsbl_site_cache, saved_site, (
void *) head);
289 new_site->
weight = weight;
291 head->
first = new_site;
300 static int psc_dnsbl_match(
const char *filter,
ARGV *reply)
308 for (cpp = reply->
argv; *cpp != 0; cpp++) {
309 if (
inet_pton(AF_INET, *cpp, addr_buf) != 1)
310 msg_warn(
"address conversion error for %s -- ignoring this reply",
321 int dnsbl_index,
int *dnsbl_ttl)
323 const char *myname =
"psc_dnsbl_retrieve";
333 msg_panic(
"%s: no blocklist score for %s", myname, client_addr);
343 result_score = score->
total;
351 *dnsbl_ttl = result_ttl;
353 msg_info(
"%s: addr=%s score=%d ttl=%d",
354 myname, client_addr, result_score, result_ttl);
358 msg_info(
"%s: delete blocklist score for %s", myname, client_addr);
361 return (result_score);
366 static void psc_dnsbl_receive(
int event,
void *context)
368 const char *myname =
"psc_dnsbl_receive";
415 msg_info(
"%s: client=\"%s\" score=%d domain=\"%s\" reply=\"%d %s\"",
416 myname,
STR(reply_client), score->
total,
417 STR(reply_dnsbl), dnsbl_ttl,
STR(reply_addr));
422 }
else if (*
STR(reply_addr) != 0) {
425 for (site = head->
first; site != 0; site = site->
next) {
427 || psc_dnsbl_match(site->
byte_codes, reply_argv ? reply_argv :
436 msg_info(
"%s: filter=\"%s\" weight=%d score=%d",
453 for (site = head->
first; site != 0; site = site->
next) {
474 msg_warn(
"dnsblog reply timeout %ds for %s",
484 void (*callback) (
int,
void *),
487 const char *myname =
"psc_dnsbl_request";
493 static int request_count;
517 if ((hash_node =
htable_locate(dnsbl_score_cache, client_addr)) != 0) {
523 msg_info(
"%s: reuse blocklist score for %s refcount=%d pending=%d",
524 myname, client_addr, score->
refcount,
531 msg_info(
"%s: create blocklist score for %s", myname, client_addr);
544 (void)
htable_enter(dnsbl_score_cache, client_addr, (
void *) score);
552 for (ht = dnsbl_site_list; *ht; ht++) {
554 msg_warn(
"%s: connect to %s service: %m",
555 myname, psc_dnsbl_service);
568 msg_warn(
"%s: error sending to %s service: %m",
569 myname, psc_dnsbl_service);
584 const char *myname =
"psc_dnsbl_init";
591 if (dnsbl_site_cache != 0)
592 msg_panic(
"%s: called more than once", myname);
606 for (cpp = dnsbl_site->
argv; *cpp; cpp++)
607 psc_dnsbl_add_site(*cpp);
#define PSC_CALL_BACK_CANCEL(sp, idx)
#define MAIL_ATTR_RBL_ADDR
#define PSC_CALL_BACK_EXTEND(hp, sp)
struct PSC_DNSBL_SITE * next
HTABLE_INFO * htable_locate(HTABLE *table, const char *key)
char * mystrdup(const char *str)
#define PSC_CALL_BACK_INIT(sp)
ARGV * argv_free(ARGV *argvp)
NORETURN msg_panic(const char *fmt,...)
#define PSC_CLEAR_EVENT_REQUEST(fd, time_act, context)
struct PSC_DNSBL_SITE PSC_DNSBL_SITE
#define CA_VSTREAM_CTL_CONTEXT(v)
#define RECV_ATTR_INT(name, val)
#define MAIL_ATTR_ACT_CLIENT_ADDR
int ip_match_execute(const char *byte_codes, const char *addr_bytes)
int var_psc_dnsbl_max_ttl
struct PSC_DNSBL_SITE * first
#define vstream_context(vp)
HTABLE * htable_create(ssize_t size)
int valid_hostname(const char *name, int gripe)
char * ip_match_save(const VSTRING *byte_codes)
HTABLE_INFO ** htable_list(HTABLE *table)
#define PSC_READ_EVENT_REQUEST(fd, action, context, timeout)
#define dict_get(dp, key)
int vstream_fclose(VSTREAM *stream)
void psc_dnsbl_init(void)
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
int inet_pton(int af, const char *src, void *dst)
void * htable_find(HTABLE *table, const char *key)
#define SEND_ATTR_INT(name, val)
int var_psc_dnsbl_min_ttl
NORETURN msg_fatal(const char *fmt,...)
int vstream_fflush(VSTREAM *stream)
int psc_dnsbl_retrieve(const char *client_addr, const char **dnsbl_name, int dnsbl_index, int *dnsbl_ttl)
char * concatenate(const char *arg0,...)
ARGV * argv_split(const char *, const char *)
char * var_dnsblog_service
char * ip_match_parse(VSTRING *byte_codes, char *pattern)
#define MAIL_ATTR_RBL_DOMAIN
VSTRING * vstring_free(VSTRING *vp)
time_t event_request_timer(EVENT_NOTIFY_TIME_FN callback, void *context, int delay)
#define PSC_CALL_BACK_INDEX_OF_LAST(sp)
char * split_at(char *string, int delimiter)
#define vstream_fileno(vp)
#define CA_VSTREAM_CTL_END
#define PSC_CALL_BACK_ENTER(sp, fn, ctx)
#define PSC_CALL_BACK_NOTIFY(sp, ev)
int psc_dnsbl_request(const char *client_addr, void(*callback)(int, void *), void *context)
void vstream_control(VSTREAM *stream, int name,...)
void htable_delete(HTABLE *table, const char *key, void(*free_fn)(void *))
char * var_psc_dnsbl_sites
#define SEND_ATTR_STR(name, val)
#define MAIL_CLASS_PRIVATE
VSTREAM * vstream_fdopen(int fd, int flags)
#define RECV_ATTR_STR(name, val)
void * mymalloc(ssize_t len)
#define MAI_HOSTADDR_STRSIZE
HTABLE_INFO * htable_enter(HTABLE *table, const char *key, void *value)
void msg_info(const char *fmt,...)