| 1 | /* |
|---|
| 2 | PowerDNS Versatile Database Driven Nameserver |
|---|
| 3 | Copyright (C) 2002-2007 PowerDNS.COM BV |
|---|
| 4 | |
|---|
| 5 | This program is free software; you can redistribute it and/or modify |
|---|
| 6 | it under the terms of the GNU General Public License version 2 |
|---|
| 7 | as published by the Free Software Foundation |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | This program is distributed in the hope that it will be useful, |
|---|
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | GNU General Public License for more details. |
|---|
| 14 | |
|---|
| 15 | You should have received a copy of the GNU General Public License |
|---|
| 16 | along with this program; if not, write to the Free Software |
|---|
| 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|---|
| 18 | */ |
|---|
| 19 | #ifndef DNSBACKEND_HH |
|---|
| 20 | #define DNSBACKEND_HH |
|---|
| 21 | |
|---|
| 22 | class DNSPacket; |
|---|
| 23 | |
|---|
| 24 | #include "utility.hh" |
|---|
| 25 | #include <string> |
|---|
| 26 | #include <vector> |
|---|
| 27 | #include <map> |
|---|
| 28 | #include <sys/types.h> |
|---|
| 29 | #include "ahuexception.hh" |
|---|
| 30 | #include <set> |
|---|
| 31 | |
|---|
| 32 | #ifndef WIN32 |
|---|
| 33 | # include <sys/socket.h> |
|---|
| 34 | # include <dirent.h> |
|---|
| 35 | #endif // WIN32 |
|---|
| 36 | |
|---|
| 37 | #include "qtype.hh" |
|---|
| 38 | #include "dns.hh" |
|---|
| 39 | #include <vector> |
|---|
| 40 | using namespace std; |
|---|
| 41 | |
|---|
| 42 | class DNSBackend; |
|---|
| 43 | struct DomainInfo |
|---|
| 44 | { |
|---|
| 45 | DomainInfo() : backend(0) {} |
|---|
| 46 | uint32_t id; |
|---|
| 47 | string zone; |
|---|
| 48 | vector<string> masters; |
|---|
| 49 | uint32_t notified_serial; |
|---|
| 50 | uint32_t serial; |
|---|
| 51 | time_t last_check; |
|---|
| 52 | enum {Master,Slave,Native} kind; |
|---|
| 53 | DNSBackend *backend; |
|---|
| 54 | |
|---|
| 55 | bool operator<(const DomainInfo& rhs) const |
|---|
| 56 | { |
|---|
| 57 | return zone < rhs.zone; |
|---|
| 58 | } |
|---|
| 59 | }; |
|---|
| 60 | |
|---|
| 61 | class DNSPacket; |
|---|
| 62 | |
|---|
| 63 | |
|---|
| 64 | //! This virtual base class defines the interface for backends for the ahudns. |
|---|
| 65 | /** To create a backend, inherit from this class and implement functions for all virtual methods. |
|---|
| 66 | Methods should not throw an exception if they are sure they did not find the requested data. However, |
|---|
| 67 | if an error occurred which prevented them temporarily from performing a lockup, they should throw a DBException, |
|---|
| 68 | which will cause the nameserver to send out a ServFail or take other evasive action. Probably only locking |
|---|
| 69 | issues should lead to DBExceptions. |
|---|
| 70 | |
|---|
| 71 | More serious errors, which may indicate that the database connection is hosed, or a configuration error occurred, should |
|---|
| 72 | lead to the throwing of an AhuException. This exception will fall straight through the UeberBackend and the PacketHandler |
|---|
| 73 | and be caught by the Distributor, which will delete your DNSBackend instance and spawn a new one. |
|---|
| 74 | */ |
|---|
| 75 | class DNSBackend |
|---|
| 76 | { |
|---|
| 77 | public: |
|---|
| 78 | //! lookup() initiates a lookup. A lookup without results should not throw! |
|---|
| 79 | virtual void lookup(const QType &qtype, const string &qdomain, DNSPacket *pkt_p=0, int zoneId=-1)=0; |
|---|
| 80 | virtual bool get(DNSResourceRecord &)=0; //!< retrieves one DNSResource record, returns false if no more were available |
|---|
| 81 | //! Initiates a list of the specified domain |
|---|
| 82 | /** Once initiated, DNSResourceRecord objects can be retrieved using get(). Should return false |
|---|
| 83 | if the backend does not consider itself responsible for the id passed. |
|---|
| 84 | \param domain_id ID of which a list is requested |
|---|
| 85 | */ |
|---|
| 86 | virtual bool list(const string &target, int domain_id)=0; |
|---|
| 87 | |
|---|
| 88 | virtual ~DNSBackend(){}; |
|---|
| 89 | |
|---|
| 90 | //! fills the soadata struct with the SOA details. Returns false if there is no SOA. |
|---|
| 91 | virtual bool getSOA(const string &name, SOAData &soadata, DNSPacket *p=0); |
|---|
| 92 | |
|---|
| 93 | //! returns true if master ip is master for domain name. |
|---|
| 94 | virtual bool isMaster(const string &name, const string &ip) |
|---|
| 95 | { |
|---|
| 96 | return false; |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | //! starts the transaction for updating domain qname (FIXME: what is id?) |
|---|
| 100 | virtual bool startTransaction(const string &qname, int id=-1) |
|---|
| 101 | { |
|---|
| 102 | return false; |
|---|
| 103 | } |
|---|
| 104 | |
|---|
| 105 | //! commits the transaction started by startTransaction |
|---|
| 106 | virtual bool commitTransaction() |
|---|
| 107 | { |
|---|
| 108 | return false; |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | //! aborts the transaction started by strartTransaction, should leave state unaltered |
|---|
| 112 | virtual bool abortTransaction() |
|---|
| 113 | { |
|---|
| 114 | return false; |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | virtual void reload() |
|---|
| 118 | { |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | virtual void rediscover(string* status=0) |
|---|
| 122 | { |
|---|
| 123 | } |
|---|
| 124 | |
|---|
| 125 | //! feeds a record to a zone, needs a call to startTransaction first |
|---|
| 126 | virtual bool feedRecord(const DNSResourceRecord &rr) |
|---|
| 127 | { |
|---|
| 128 | return false; // no problem! |
|---|
| 129 | } |
|---|
| 130 | //! if this returns true, DomainInfo di contains information about the domain |
|---|
| 131 | virtual bool getDomainInfo(const string &domain, DomainInfo &di) |
|---|
| 132 | { |
|---|
| 133 | return false; |
|---|
| 134 | } |
|---|
| 135 | //! slave capable backends should return a list of slaves that should be rechecked for staleness |
|---|
| 136 | virtual void getUnfreshSlaveInfos(vector<DomainInfo>* domains) |
|---|
| 137 | { |
|---|
| 138 | } |
|---|
| 139 | |
|---|
| 140 | //! get a list of IP addresses that should also be notified for a domain |
|---|
| 141 | virtual void alsoNotifies(const string &domain, set<string> *ips) |
|---|
| 142 | { |
|---|
| 143 | } |
|---|
| 144 | |
|---|
| 145 | //! get list of domains that have been changed since their last notification to slaves |
|---|
| 146 | virtual void getUpdatedMasters(vector<DomainInfo>* domains) |
|---|
| 147 | { |
|---|
| 148 | } |
|---|
| 149 | |
|---|
| 150 | //! Called by PowerDNS to inform a backend that a domain has been checked for freshness |
|---|
| 151 | virtual void setFresh(uint32_t domain_id) |
|---|
| 152 | { |
|---|
| 153 | |
|---|
| 154 | } |
|---|
| 155 | //! Called by PowerDNS to inform a backend that the changes in the domain have been reported to slaves |
|---|
| 156 | virtual void setNotified(uint32_t id, uint32_t serial) |
|---|
| 157 | { |
|---|
| 158 | } |
|---|
| 159 | |
|---|
| 160 | //! Can be called to seed the getArg() function with a prefix |
|---|
| 161 | void setArgPrefix(const string &prefix); |
|---|
| 162 | |
|---|
| 163 | //! determine if ip is a supermaster or a domain |
|---|
| 164 | virtual bool superMasterBackend(const string &ip, const string &domain, const vector<DNSResourceRecord>&nsset, string *account, DNSBackend **db) |
|---|
| 165 | { |
|---|
| 166 | return false; |
|---|
| 167 | } |
|---|
| 168 | |
|---|
| 169 | //! called by PowerDNS to create a slave record for a superMaster |
|---|
| 170 | virtual bool createSlaveDomain(const string &ip, const string &domain, const string &account) |
|---|
| 171 | { |
|---|
| 172 | return false; |
|---|
| 173 | } |
|---|
| 174 | |
|---|
| 175 | protected: |
|---|
| 176 | bool mustDo(const string &key); |
|---|
| 177 | const string &getArg(const string &key); |
|---|
| 178 | int getArgAsNum(const string &key); |
|---|
| 179 | string getRemote(DNSPacket *p); |
|---|
| 180 | bool getRemote(DNSPacket *p, struct sockaddr *in, Utility::socklen_t *len); |
|---|
| 181 | |
|---|
| 182 | private: |
|---|
| 183 | string d_prefix; |
|---|
| 184 | }; |
|---|
| 185 | |
|---|
| 186 | class BackendFactory |
|---|
| 187 | { |
|---|
| 188 | public: |
|---|
| 189 | BackendFactory(const string &name) : d_name(name) {} |
|---|
| 190 | virtual ~BackendFactory(){} |
|---|
| 191 | virtual DNSBackend *make(const string &suffix)=0; |
|---|
| 192 | virtual void declareArguments(const string &suffix=""){} |
|---|
| 193 | const string &getName() const; |
|---|
| 194 | |
|---|
| 195 | protected: |
|---|
| 196 | void declare(const string &suffix, const string ¶m, const string &explanation, const string &value); |
|---|
| 197 | |
|---|
| 198 | private: |
|---|
| 199 | const string d_name; |
|---|
| 200 | }; |
|---|
| 201 | |
|---|
| 202 | class BackendMakerClass |
|---|
| 203 | { |
|---|
| 204 | public: |
|---|
| 205 | void report(BackendFactory *bf); |
|---|
| 206 | void launch(const string &instr); |
|---|
| 207 | vector<DNSBackend *>all(); |
|---|
| 208 | void load(const string &module); |
|---|
| 209 | int numLauncheable(); |
|---|
| 210 | vector<string> getModules(); |
|---|
| 211 | |
|---|
| 212 | private: |
|---|
| 213 | void load_all(); |
|---|
| 214 | typedef map<string,BackendFactory *>d_repository_t; |
|---|
| 215 | d_repository_t d_repository; |
|---|
| 216 | vector<pair<string,string> >d_instances; |
|---|
| 217 | }; |
|---|
| 218 | |
|---|
| 219 | extern BackendMakerClass &BackendMakers(); |
|---|
| 220 | |
|---|
| 221 | //! Exception that can be thrown by a DNSBackend to indicate a failure |
|---|
| 222 | class DBException : public AhuException |
|---|
| 223 | { |
|---|
| 224 | public: |
|---|
| 225 | DBException(const string &reason) : AhuException(reason){} |
|---|
| 226 | }; |
|---|
| 227 | |
|---|
| 228 | |
|---|
| 229 | #endif |
|---|