// -*-c++-*- /* $Id: dnsimpl.h,v 1.5 2005/07/18 21:23:18 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 * */ #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 hlink; // Per-id hash table link tmoq_entry 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 vnames; vec vrfyv; static void maybe_push (vec *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 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::ref cb_t; protected: cb_t cb; ref destroyed; public: const bool reliable; dnssock (bool r, cb_t c) : cb (c), destroyed (New refcounted (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 udpsock; ptr 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 h, int err); public: time_t last_resp; // Last time of valid reply from this server time_t last_bump; ref destroyed; ihash reqtab; tmoq 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 destroyed; void reload (bool failure); static void reload_dumpres (int fd); void reload_cb (ref d, bool ifchange, str newres); protected: bool bumpsock (bool failure); public: resolv_conf (); ~resolv_conf (); const char *srchlist (int n); }; #endif /* _ASYNC_DNSIMPL_H_ */