1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
// -*-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
*
*/
#ifndef _ASYNC_DNSIMPL_H_
#define _ASYNC_DNSIMPL_H_ 1
#include "dnsparse.h"
#include "ihash.h"
#include "backoff.h"
class resolver;
class dnsreq {
int ntries;
int srchno;
public:
resolver *const resp;
bool usetcp;
private:
bool constructed;
bool intable;
protected:
void remove ();
public:
int error;
u_int16_t id; // DNS query ID
str basename; // Name for which to search
str name; // Name for which to query
u_int16_t type; // Type of query (T_A, T_PTR, etc.)
ihash_entry<dnsreq> hlink; // Per-id hash table link
tmoq_entry<dnsreq> tlink; // Retransmit queue link
dnsreq (resolver *, str, u_int16_t, bool search = false);
virtual ~dnsreq ();
void start (bool);
void xmit (int = 0);
virtual void readreply (dnsparse *) = 0;
void timeout ();
void fail (int);
};
class dnsreq_a : public dnsreq {
bool checkaddr; // Non-zero when arr_addr must be checked
in_addr addr; // Adress of inverse queries (for checking)
cbhent cb; // Callback for hostbyname/addr
dnsreq_a ();
public:
dnsreq_a (resolver *rp, str n, cbhent c, bool s = false)
: dnsreq (rp, n, T_A, s), checkaddr (false), cb (c) {}
dnsreq_a (resolver *rp, str n, cbhent c, const in_addr &a)
: dnsreq (rp, n, T_A), checkaddr (true), addr (a), cb (c) {}
void readreply (dnsparse *);
};
class dnsreq_mx : public dnsreq {
cbmxlist cb;
dnsreq_mx ();
public:
dnsreq_mx (resolver *rp, str n, cbmxlist c, bool s)
: dnsreq (rp, n, T_MX, s), cb (c) {}
void readreply (dnsparse *);
};
class dnsreq_srv : public dnsreq {
cbsrvlist cb;
dnsreq_srv ();
public:
dnsreq_srv (resolver *rp, str n, cbsrvlist c, bool s)
: dnsreq (rp, n, T_SRV, s), cb (c) {}
void readreply (dnsparse *);
};
class dnsreq_ptr : public dnsreq {
in_addr addr;
cbhent cb; // Callback for hostbyname/addr
int napending;
vec<str, 2> vnames;
vec<dnsreq_a *> vrfyv;
static void maybe_push (vec<str, 2> *sv, const char *s);
public:
static str inaddr_arpa (in_addr);
dnsreq_ptr (resolver *rp, in_addr a, cbhent c)
: dnsreq (rp, inaddr_arpa (a), T_PTR), addr (a), cb (c) {}
~dnsreq_ptr ();
void readreply (dnsparse *);
void readvrfy (int i, ptr<hostent> h, int err);
};
class dnsreq_txt : public dnsreq {
cbtxtlist cb;
public:
dnsreq_txt (resolver *rp, str n, cbtxtlist c, bool s = false)
: dnsreq (rp, n, T_TXT, s), cb (c) {}
void readreply (dnsparse *);
};
class dnssock {
public:
typedef callback<void, u_char *, ssize_t>::ref cb_t;
protected:
cb_t cb;
ref<bool> destroyed;
public:
const bool reliable;
dnssock (bool r, cb_t c)
: cb (c), destroyed (New refcounted<bool> (false)),
reliable (r) {}
virtual ~dnssock () { *destroyed = false; }
virtual void sendpkt (const u_char *pkt, size_t size) = 0;
};
class dnssock_udp : public dnssock {
int fd;
void rcb ();
public:
dnssock_udp (int f, cb_t cb);
~dnssock_udp ();
void sendpkt (const u_char *pkt, size_t size);
};
class dnssock_tcp : public dnssock {
int fd;
bool write_ok;
dnstcppkt tcpstate;
void rcb ();
void wcb (bool selected = false);
public:
dnssock_tcp (int f, cb_t cb);
~dnssock_tcp ();
void sendpkt (const u_char *pkt, size_t size);
};
class resolver {
protected:
ptr<dnssock> udpsock;
ptr<dnssock> tcpsock;
int nbump; // # of bumpsocks since last good reply
sockaddr *addr;
socklen_t addrlen;
dnsreq *udpcheck_req;
virtual bool bumpsock (bool failure) = 0;
bool udpinit ();
bool tcpinit ();
void cantsend ();
bool resend (bool udp, bool tcp);
static void failreq (int err, dnsreq *r) { r->fail (err); }
void pktready (bool tcp, u_char *qb, ssize_t size);
void udpcheck_cb (ptr<hostent> h, int err);
public:
time_t last_resp; // Last time of valid reply from this server
time_t last_bump;
ref<bool> destroyed;
ihash<u_int16_t, dnsreq, &dnsreq::id, &dnsreq::hlink> reqtab;
tmoq<dnsreq, &dnsreq::tlink, 1, 5> reqtoq;
resolver ();
virtual ~resolver ();
bool setsock (bool failure);
void sendreq (dnsreq *r);
virtual const char *srchlist (int n) { return n <= 0 ? "" : NULL; }
u_int16_t genid ();
void udpcheck ();
};
class resolv_conf : public resolver {
protected:
int ns_idx;
sockaddr_in srvaddr;
time_t last_reload;
bool reload_lock;
ifchgcb_t *ifc;
ref<bool> destroyed;
void reload (bool failure);
static void reload_dumpres (int fd);
void reload_cb (ref<bool> d, bool ifchange, str newres);
protected:
bool bumpsock (bool failure);
public:
resolv_conf ();
~resolv_conf ();
const char *srchlist (int n);
};
#endif /* _ASYNC_DNSIMPL_H_ */
|