/* $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 stat; int nleft; rbl_check (ref st, cbv c) : cb (c), stat (st) {} void init_con (in_addr addr, str hostname, const vec > &rblv); void init_env (str hostname, const vec > &rblv); void result (ref rp, ptr h, int err); void finish (); }; void rbl_check::init_con (in_addr addr, str hostname, const vec > &rblv) { u_char *a = reinterpret_cast (&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 > &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 rp, ptr 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 rs, const vec > &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 rs, const vec > &rblv, str hostname, cbv cb) { rbl_check *rc = New rbl_check (rs, cb); rc->init_env (hostname, rblv); }