]>
Commit | Line | Data |
---|---|---|
12c86877 | 1 | /* |
12471842 PL |
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 | */ | |
12c86877 | 22 | #ifndef DNSPACKET_HH |
24d09b7c | 23 | |
12c86877 BH |
24 | #define DNSPACKET_HH |
25 | ||
26 | #include <cstdio> | |
27 | #include <cstring> | |
28 | #include <cstdlib> | |
1258abe0 | 29 | #include <sys/types.h> |
809fe23f | 30 | #include "iputils.hh" |
af7d3ea6 | 31 | #include "ednssubnet.hh" |
55b524a0 | 32 | #include <unordered_set> |
12c86877 BH |
33 | #include <sys/socket.h> |
34 | #include <netinet/in.h> | |
35 | #include <sys/time.h> | |
1258abe0 BH |
36 | #include <unistd.h> |
37 | #include <arpa/inet.h> | |
38 | ||
12c86877 BH |
39 | #include <iostream> |
40 | #include <string> | |
12c86877 BH |
41 | #include <vector> |
42 | #include "qtype.hh" | |
43 | #include "dns.hh" | |
44 | #include "misc.hh" | |
45 | #include "utility.hh" | |
46 | #include "logger.hh" | |
5c409fa2 | 47 | #include "pdnsexception.hh" |
78bcb858 | 48 | #include "dnsrecords.hh" |
12c86877 | 49 | |
3971cf53 | 50 | class UeberBackend; |
e0d84497 | 51 | class DNSSECKeeper; |
34b37bbb | 52 | |
90ba52e0 | 53 | |
12c86877 BH |
54 | //! This class represents DNS packets, either received or to be sent. |
55 | class DNSPacket | |
56 | { | |
57 | public: | |
27c0050c | 58 | DNSPacket(bool isQuery); |
12c86877 BH |
59 | DNSPacket(const DNSPacket &orig); |
60 | ||
a683e8bd RG |
61 | int noparse(const char *mesg, size_t len); //!< just suck the data inward |
62 | int parse(const char *mesg, size_t len); //!< parse a raw UDP or TCP packet and suck the data inward | |
78bcb858 | 63 | const string& getString(); //!< for serialization - just passes the whole packet |
12c86877 | 64 | |
34b37bbb | 65 | // address & socket manipulation |
b8e0f341 | 66 | void setRemote(const ComboAddress*); |
b9b4da23 | 67 | ComboAddress getRemote() const; |
af7d3ea6 | 68 | Netmask getRealRemote() const; |
b9b4da23 | 69 | ComboAddress getLocal() const |
88c1bc50 BH |
70 | { |
71 | ComboAddress ca; | |
72 | socklen_t len=sizeof(ca); | |
73 | getsockname(d_socket, (sockaddr*)&ca, &len); | |
b9b4da23 | 74 | return ca; |
88c1bc50 | 75 | } |
092f210a | 76 | uint16_t getRemotePort() const; |
2b6f1436 BH |
77 | |
78 | boost::optional<ComboAddress> d_anyLocal; | |
12c86877 | 79 | |
34b37bbb BH |
80 | Utility::sock_t getSocket() const |
81 | { | |
82 | return d_socket; | |
83 | } | |
b8e0f341 | 84 | void setSocket(Utility::sock_t sock); |
34b37bbb BH |
85 | |
86 | ||
87 | // these manipulate 'd' | |
88 | void setA(bool); //!< make this packet authoritative - manipulates 'd' | |
89 | void setID(uint16_t); //!< set the DNS id of this packet - manipulates 'd' | |
90 | void setRA(bool); //!< set the Recursion Available flag - manipulates 'd' | |
91 | void setRD(bool); //!< set the Recursion Desired flag - manipulates 'd' | |
92 | void setAnswer(bool); //!< Make this packet an answer - clears the 'stringbuffer' first, if passed 'true', does nothing otherwise, manipulates 'd' | |
12c86877 | 93 | |
34b37bbb BH |
94 | void setOpcode(uint16_t); //!< set the Opcode of this packet - manipulates 'd' |
95 | void setRcode(int v); //!< set the Rcode of this packet - manipulates 'd' | |
96 | ||
97 | void clearRecords(); //!< when building a packet, wipe all previously added records (clears 'rrs') | |
77235722 | 98 | |
90ba52e0 | 99 | /** Add a DNSZoneRecord to this packet. A DNSPacket (as does a DNS Packet) has 4 kinds of resource records. Questions, |
12c86877 | 100 | Answers, Authority and Additional. See RFC 1034 and 1035 for details. You can specify where a record needs to go in the |
90ba52e0 | 101 | DNSZoneRecord d_place field */ |
102 | void addRecord(const DNSZoneRecord &); // adds to 'rrs' | |
34b37bbb | 103 | |
c2f3be9d | 104 | void setQuestion(int op, const DNSName &qdomain, int qtype); // wipes 'd', sets a random id, creates start of packet (domain, type, class etc) |
34b37bbb BH |
105 | |
106 | DTime d_dt; //!< the time this packet was created. replyPacket() copies this in for you, so d_dt becomes the time spent processing the question+answer | |
e02d0a59 | 107 | void wrapup(); // writes out queued rrs, and generates the binary packet. also shuffles. also rectifies dnsheader 'd', and copies it to the stringbuffer |
63e365db | 108 | void spoofQuestion(const DNSPacket *qd); //!< paste in the exact right case of the question. Useful for PacketCache |
b35ea8ec | 109 | unsigned int getMinTTL(); //!< returns lowest TTL of any record in the packet |
9951e2d0 | 110 | bool isEmpty(); //!< returns true if there are no rrs in the packet |
34b37bbb | 111 | |
90ba52e0 | 112 | vector<DNSZoneRecord*> getAPRecords(); //!< get a vector with DNSZoneRecords that need additional processing |
113 | vector<DNSZoneRecord*> getAnswerRecords(); //!< get a vector with DNSZoneRecords that are answers | |
34b37bbb BH |
114 | void setCompress(bool compress); |
115 | ||
116 | DNSPacket *replyPacket() const; //!< convenience function that creates a virgin answer packet to this question | |
117 | ||
b8e0f341 | 118 | void commitD(); //!< copies 'd' into the stringbuffer |
78bcb858 | 119 | unsigned int getMaxReplyLen(); //!< retrieve the maximum length of the packet we should send in response |
80397312 | 120 | void setMaxReplyLen(int bytes); //!< set the max reply len (used when retrieving from the packet cache, and this changed) |
7f7b8d55 BH |
121 | |
122 | bool couldBeCached(); //!< returns 0 if this query should bypass the packet cache | |
02980dc2 | 123 | bool hasEDNSSubnet() const; |
17d0b1e6 | 124 | bool hasEDNS(); |
298fabc3 AT |
125 | uint8_t getEDNSVersion() const { return d_ednsversion; }; |
126 | void setEDNSRcode(uint16_t extRCode) | |
127 | { | |
128 | // WARNING: this is really 12 bits | |
129 | d_ednsrcode=extRCode; | |
130 | }; | |
131 | uint8_t getEDNSRCode() const { return d_ednsrcode; }; | |
bf269e28 RG |
132 | uint32_t getHash() const { return d_hash; }; |
133 | void setHash(uint32_t hash) { d_hash = hash; }; | |
134 | ||
34b37bbb | 135 | //////// DATA ! |
12c86877 | 136 | |
c2f3be9d PD |
137 | DNSName qdomain; //!< qname of the question 4 - unsure how this is used |
138 | DNSName qdomainwild; //!< wildcard matched by qname, used by LuaPolicyEngine | |
139 | DNSName qdomainzone; //!< zone name for the answer (as reflected in SOA for negative responses), used by LuaPolicyEngine | |
921d0747 | 140 | string d_peer_principal; |
1a5ac5d7 AT |
141 | const DNSName& getTSIGKeyname() const; |
142 | ||
921d0747 PL |
143 | struct dnsheader d; //!< dnsheader at the start of the databuffer 12 |
144 | ||
921d0747 PL |
145 | TSIGRecordContent d_trc; //72 |
146 | ||
147 | ComboAddress d_remote; //28 | |
eace2c24 | 148 | TSIGHashEnum d_tsig_algo{TSIG_MD5}; //4 |
921d0747 | 149 | |
f93ad391 | 150 | int d_ednsRawPacketSizeLimit{-1}; // only used for Lua record |
eace2c24 RG |
151 | uint16_t qclass{QClass::IN}; //!< class of the question - should always be INternet 2 |
152 | QType qtype; //!< type of the question 2 | |
153 | ||
154 | bool d_tcp{false}; | |
155 | bool d_dnssecOk{false}; | |
156 | bool d_havetsig{false}; | |
78bcb858 | 157 | |
ea3816cf | 158 | bool getTSIGDetails(TSIGRecordContent* tr, DNSName* keyname, uint16_t* tsigPos=nullptr) const; |
675fa24c PD |
159 | void setTSIGDetails(const TSIGRecordContent& tr, const DNSName& keyname, const string& secret, const string& previous, bool timersonly=false); |
160 | bool getTKEYRecord(TKEYRecordContent* tr, DNSName* keyname) const; | |
4429ed62 | 161 | |
90ba52e0 | 162 | vector<DNSZoneRecord>& getRRS() { return d_rrs; } |
ea3816cf RG |
163 | bool checkForCorrectTSIG(UeberBackend* B, DNSName* keyname, string* secret, TSIGRecordContent* trc) const; |
164 | ||
779b8a25 | 165 | static uint16_t s_udpTruncationThreshold; |
eace2c24 RG |
166 | static bool s_doEDNSSubnetProcessing; |
167 | ||
12c86877 | 168 | private: |
34b37bbb BH |
169 | void pasteQ(const char *question, int length); //!< set the question of this packet, useful for crafting replies |
170 | ||
78bcb858 | 171 | string d_tsigsecret; |
675fa24c | 172 | DNSName d_tsigkeyname; |
78bcb858 | 173 | string d_tsigprevious; |
78bcb858 | 174 | |
90ba52e0 | 175 | vector<DNSZoneRecord> d_rrs; // 8 |
9d40dd1f | 176 | std::unordered_set<size_t> d_dedup; |
921d0747 | 177 | string d_rawpacket; // this is where everything lives 8 |
921d0747 PL |
178 | EDNSSubnetOpts d_eso; |
179 | ||
eace2c24 RG |
180 | int d_maxreplylen{0}; |
181 | int d_socket{-1}; // 4 | |
bf269e28 | 182 | uint32_t d_hash{0}; |
eace2c24 RG |
183 | // WARNING! This is really 12 bits |
184 | uint16_t d_ednsrcode{0}; | |
185 | uint8_t d_ednsversion{0}; | |
186 | ||
187 | bool d_wrapped{false}; // 1 | |
188 | bool d_compress{true}; // 1 | |
189 | bool d_tsigtimersonly{false}; | |
190 | bool d_wantsnsid{false}; | |
191 | bool d_haveednssubnet{false}; | |
192 | bool d_haveednssection{false}; | |
27c0050c | 193 | bool d_isQuery; |
12c86877 BH |
194 | }; |
195 | ||
12c86877 | 196 | #endif |