/* $Id: rbl.C,v 1.3 2004/08/05 23:44:26 dm Exp $ */
/*
*
* Copyright (C) 2003 David Mazieres (dm@uun.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*/
#include "asmtpd.h"
rbl::rbl (str d, u_int f, int s)
: domain (d), flags (f), score (s)
{
}
void
rbl_status::result::addval (in_addr addr)
{
for (const in_addr *ap = vals.base (); ap < vals.lim (); ap++)
if (ap->s_addr == addr.s_addr)
return;
vals.push_back (addr);
}
bool
rbl_status::result::hasval (in_addr addr) const
{
for (const in_addr *ap = vals.base (); ap < vals.lim (); ap++)
if (ap->s_addr == addr.s_addr)
return true;
return false;
}
str
rbl_status::result::tostr (bool env) const
{
assert (!vals.empty ());
strbuf sb;
if (env) {
sb << "RBL_";
char *p = sb.tosuio ()->getspace (name.len ());
for (u_int i = 0; i < name.len (); i++)
p[i] = isalpha (name[i]) ? name[i] : '_';
sb.tosuio ()->print (p, name.len ());
sb << "=";
}
else
sb << name << " (";
sb << inet_ntoa (vals[0]);
for (const in_addr *ap = vals.base () + 1; ap < vals.lim (); ap++)
sb << " " << inet_ntoa (*ap);
if (!env)
sb << ")";
return sb;
}
void
rbl_status::addresult (const rbl *rblp, in_addr val)
{
result *rp;
for (rp = results.base (); rp < results.lim (); rp++)
if (rp->name == rblp->domain)
break;
if (rp < results.lim ()) {
if (!rp->hasval (val)) {
score += rblp->score;
rp->vals.push_back (val);
}
}
else {
score += rblp->score;
result &r = results.push_back ();
r.name = rblp->domain;
r.vals.push_back (val);
}
}
struct rbl_check {
const cbv cb;
ref<rbl_status> stat;
int nleft;
rbl_check (ref<rbl_status> st, cbv c) : cb (c), stat (st) {}
void init_con (in_addr addr, str hostname, const vec<ref<rbl> > &rblv);
void init_env (str hostname, const vec<ref<rbl> > &rblv);
void result (ref<rbl> rp, ptr<hostent> h, int err);
void finish ();
};
void
rbl_check::init_con (in_addr addr, str hostname, const vec<ref<rbl> > &rblv)
{
u_char *a = reinterpret_cast<u_char *> (&addr);
nleft = 1;
for (u_int i = 0; i < rblv.size (); i++) {
if (!(rblv[i]->flags & (rbl::QUERY_IP | rbl::QUERY_PTR)))
continue;
if ((rblv[i]->flags & rbl::QUERY_PTR) && hostname) {
nleft++;
str name = hostname << "." << rblv[i]->domain;
dns_hostbyname (name, wrap (this, &rbl_check::result, rblv[i]),
false, false);
}
if (rblv[i]->flags & rbl::QUERY_IP) {
nleft++;
str name = (strbuf ("%d.%d.%d.%d.", a[3], a[2], a[1], a[0])
<< rblv[i]->domain);
dns_hostbyname (name, wrap (this, &rbl_check::result, rblv[i]),
false, false);
}
}
finish ();
}
void
rbl_check::init_env (str hostname, const vec<ref<rbl> > &rblv)
{
nleft = 1;
for (u_int i = 0; i < rblv.size (); i++) {
if (!(rblv[i]->flags & rbl::QUERY_ENV))
continue;
str name = hostname << "." << rblv[i]->domain;
nleft++;
dns_hostbyname (name, wrap (this, &rbl_check::result, rblv[i]),
false, false);
}
finish ();
}
void
rbl_check::result (ref<rbl> rp, ptr<hostent> h, int err)
{
if (h) {
if (rp->flags & rbl::TRUSTED)
stat->trusted = true;
for (char **ap = h->h_addr_list; *ap; ap++)
stat->addresult (rp, *(in_addr *) *ap);
}
else if (dns_tmperr (err)) {
rbl_status::rblerr *ep;
for (ep = stat->errors.base ();
ep < stat->errors.lim () && ep->name != rp->domain; ep++)
;
if (ep >= stat->errors.lim ())
stat->errors.push_back (rbl_status::rblerr (rp->domain, err));
maybe_warn (strbuf () << rp->domain << ": " << dns_strerror (err) << "\n");
}
finish ();
}
void
rbl_check::finish ()
{
if (--nleft)
return;
(*cb) ();
delete this;
}
void
rbl_check_con (ref<rbl_status> rs, const vec<ref<rbl> > &rblv,
in_addr addr, str hostname, cbv cb)
{
rbl_check *rc = New rbl_check (rs, cb);
rc->init_con (addr, hostname, rblv);
}
void
rbl_check_env (ref<rbl_status> rs, const vec<ref<rbl> > &rblv,
str hostname, cbv cb)
{
rbl_check *rc = New rbl_check (rs, cb);
rc->init_env (hostname, rblv);
}
syntax highlighted by Code2HTML, v. 0.9.1