1 /*
2  * This file is part of PowerDNS or dnsdist.
3  * Copyright -- PowerDNS.COM B.V. and its contributors
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * In addition, for the avoidance of any doubt, permission is granted to
10  * link this program with OpenSSL and to (re)distribute the binaries
11  * produced as the result of such linking.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 #pragma once
23 #include <boost/multi_index_container.hpp>
24 #include <boost/multi_index/ordered_index.hpp>
25 #include <boost/tuple/tuple_comparison.hpp>
26 #include <boost/multi_index/key_extractors.hpp>
27 #include <boost/multi_index/sequenced_index.hpp>
28 #include "qtype.hh"
29 #include "dnsname.hh"
30 #include <time.h>
31 #include <sys/types.h>
32 
33 #undef BADSIG  // signal.h SIG_ERR
34 
35 class DNSBackend;
36 struct DNSRecord;
37 
38 struct SOAData
39 {
SOADataSOAData40   SOAData() : ttl(0), serial(0), refresh(0), retry(0), expire(0), minimum(0), db(0), domain_id(-1) {};
41 
42   DNSName qname;
43   DNSName nameserver;
44   DNSName hostmaster;
45   uint32_t ttl;
46   uint32_t serial;
47   uint32_t refresh;
48   uint32_t retry;
49   uint32_t expire;
50   uint32_t minimum;
51   DNSBackend *db;
52   int domain_id;
53 
getNegativeTTLSOAData54   uint32_t getNegativeTTL() const { return min(ttl, minimum); }
55 };
56 
57 class RCode
58 {
59 public:
60   enum rcodes_ { NoError=0, FormErr=1, ServFail=2, NXDomain=3, NotImp=4, Refused=5, YXDomain=6, YXRRSet=7, NXRRSet=8, NotAuth=9, NotZone=10};
61   static std::string to_s(uint8_t rcode);
62   static std::vector<std::string> rcodes_s;
63 };
64 
65 class ERCode
66 {
67 public:
68   enum rcodes_ { BADVERS=16, BADSIG=16, BADKEY=17, BADTIME=18, BADMODE=19, BADNAME=20, BADALG=21, BADTRUNC=22, BADCOOKIE=23 };
69   static std::string to_s(uint8_t rcode);
70 };
71 
72 class Opcode
73 {
74 public:
75   enum { Query=0, IQuery=1, Status=2, Notify=4, Update=5 };
76   static std::string to_s(uint8_t opcode);
77 };
78 
79 //! This class represents a resource record
80 class DNSResourceRecord
81 {
82 public:
DNSResourceRecord()83   DNSResourceRecord() : last_modified(0), ttl(0), signttl(0), domain_id(-1), qclass(1), scopeMask(0), auth(1), disabled(0) {};
84   static DNSResourceRecord fromWire(const DNSRecord& d);
85 
86   enum Place : uint8_t {QUESTION=0, ANSWER=1, AUTHORITY=2, ADDITIONAL=3}; //!< Type describing the positioning within, say, a DNSPacket
87 
88   void setContent(const string& content);
89   string getZoneRepresentation(bool noDot=false) const;
90 
91   // data
92   DNSName qname; //!< the name of this record, for example: www.powerdns.com
93   DNSName ordername;
94   DNSName wildcardname;
95   string content; //!< what this record points to. Example: 10.1.2.3
96 
97   // Aligned on 8-byte boundaries on systems where time_t is 8 bytes and int
98   // is 4 bytes, aka modern linux on x86_64
99   time_t last_modified; //!< For autocalculating SOA serial numbers - the backend needs to fill this in
100 
101   uint32_t ttl; //!< Time To Live of this record
102   uint32_t signttl; //!< If non-zero, use this TTL as original TTL in the RRSIG
103 
104   int domain_id; //!< If a backend implements this, the domain_id of the zone this record is in
105   QType qtype; //!< qtype of this record, ie A, CNAME, MX etc
106   uint16_t qclass; //!< class of this record
107 
108   uint8_t scopeMask;
109   bool auth;
110   bool disabled;
111 
112   bool operator==(const DNSResourceRecord& rhs);
113 
operator <(const DNSResourceRecord & b) const114   bool operator<(const DNSResourceRecord &b) const
115   {
116     if(qname < b.qname)
117       return true;
118     if(qname == b.qname)
119       return(content < b.content);
120     return false;
121   }
122 };
123 
124 #define GCCPACKATTRIBUTE __attribute__((packed))
125 
126 struct dnsrecordheader
127 {
128   uint16_t d_type;
129   uint16_t d_class;
130   uint32_t d_ttl;
131   uint16_t d_clen;
132 } GCCPACKATTRIBUTE;
133 
134 struct EDNS0Record
135 {
136   uint8_t extRCode, version;
137   uint16_t extFlags;
138 } GCCPACKATTRIBUTE;
139 
140 static_assert(sizeof(EDNS0Record) == 4, "EDNS0Record size must be 4");
141 
142 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
143 #include <machine/endian.h>
144 #elif __linux__ || __GNU__
145 # include <endian.h>
146 
147 #else  // with thanks to <arpa/nameser.h>
148 
149 # define LITTLE_ENDIAN   1234    /* least-significant byte first (vax, pc) */
150 # define BIG_ENDIAN      4321    /* most-significant byte first (IBM, net) */
151 # define PDP_ENDIAN      3412    /* LSB first in word, MSW first in long (pdp) */
152 
153 #if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \
154         defined(__i386) || defined(__ia64) || defined(__amd64) || \
155         defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \
156         defined(__alpha__) || defined(__alpha) || \
157         (defined(__Lynx__) && defined(__x86__))
158 # define BYTE_ORDER      LITTLE_ENDIAN
159 #endif
160 
161 #if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
162     defined(__sparc) || \
163     defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \
164     defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\
165     defined(apollo) || defined(__convex__) || defined(_CRAY) || \
166     defined(__hppa) || defined(__hp9000) || \
167     defined(__hp9000s300) || defined(__hp9000s700) || \
168     defined(__hp3000s900) || defined(MPE) || \
169     defined(BIT_ZERO_ON_LEFT) || defined(m68k) || \
170         (defined(__Lynx__) && \
171         (defined(__68k__) || defined(__sparc__) || defined(__powerpc__)))
172 # define BYTE_ORDER      BIG_ENDIAN
173 #endif
174 
175 #endif
176 
177 struct dnsheader {
178         unsigned        id :16;         /* query identification number */
179 #if BYTE_ORDER == BIG_ENDIAN
180                         /* fields in third byte */
181         unsigned        qr: 1;          /* response flag */
182         unsigned        opcode: 4;      /* purpose of message */
183         unsigned        aa: 1;          /* authoritative answer */
184         unsigned        tc: 1;          /* truncated message */
185         unsigned        rd: 1;          /* recursion desired */
186                         /* fields in fourth byte */
187         unsigned        ra: 1;          /* recursion available */
188         unsigned        unused :1;      /* unused bits (MBZ as of 4.9.3a3) */
189         unsigned        ad: 1;          /* authentic data from named */
190         unsigned        cd: 1;          /* checking disabled by resolver */
191         unsigned        rcode :4;       /* response code */
192 #elif BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
193                         /* fields in third byte */
194         unsigned        rd :1;          /* recursion desired */
195         unsigned        tc :1;          /* truncated message */
196         unsigned        aa :1;          /* authoritative answer */
197         unsigned        opcode :4;      /* purpose of message */
198         unsigned        qr :1;          /* response flag */
199                         /* fields in fourth byte */
200         unsigned        rcode :4;       /* response code */
201         unsigned        cd: 1;          /* checking disabled by resolver */
202         unsigned        ad: 1;          /* authentic data from named */
203         unsigned        unused :1;      /* unused bits (MBZ as of 4.9.3a3) */
204         unsigned        ra :1;          /* recursion available */
205 #endif
206                         /* remaining bytes */
207         unsigned        qdcount :16;    /* number of question entries */
208         unsigned        ancount :16;    /* number of answer entries */
209         unsigned        nscount :16;    /* number of authority entries */
210         unsigned        arcount :16;    /* number of resource entries */
211 };
212 
213 static_assert(sizeof(dnsheader) == 12, "dnsheader size must be 12");
214 
getFlagsFromDNSHeader(struct dnsheader * dh)215 inline uint16_t * getFlagsFromDNSHeader(struct dnsheader * dh)
216 {
217   return (uint16_t*) (((char *) dh) + sizeof(uint16_t));
218 }
219 
220 #define DNS_TYPE_SIZE (2)
221 #define DNS_CLASS_SIZE (2)
222 #define DNS_TTL_SIZE (4)
223 #define DNS_RDLENGTH_SIZE (2)
224 #define EDNS_EXTENDED_RCODE_SIZE (1)
225 #define EDNS_VERSION_SIZE (1)
226 #define EDNS_OPTION_CODE_SIZE (2)
227 #define EDNS_OPTION_LENGTH_SIZE (2)
228 
229 #if BYTE_ORDER == BIG_ENDIAN
230 #define FLAGS_RD_OFFSET (8)
231 #define FLAGS_CD_OFFSET (12)
232 #elif BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
233 #define FLAGS_RD_OFFSET (0)
234 #define FLAGS_CD_OFFSET (12)
235 #endif
236 
237 extern time_t s_starttime;
238 
239 uint32_t hashQuestion(const char* packet, uint16_t len, uint32_t init);
240 
241 struct TSIGTriplet
242 {
243   DNSName name, algo;
244   string secret;
245 };
246 
247 string &attodot(string &str);  //!< for when you need to insert an email address in the SOA
248