Logo Search packages:      
Sourcecode: mailavenger version File versions  Download package

rbl.C

/* $Id$ */

/*
 *
 * 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);
}

Generated by  Doxygen 1.6.0   Back to index