]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnspacket.hh
auth: switch circleci mssql image
[thirdparty/pdns.git] / pdns / dnspacket.hh
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 #ifndef DNSPACKET_HH
23
24 #define DNSPACKET_HH
25
26 #include <cstdio>
27 #include <cstring>
28 #include <cstdlib>
29 #include <sys/types.h>
30 #include "iputils.hh"
31 #include "ednssubnet.hh"
32 #include <unordered_set>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <sys/time.h>
36 #include <unistd.h>
37 #include <arpa/inet.h>
38
39 #include <iostream>
40 #include <string>
41 #include <vector>
42 #include "qtype.hh"
43 #include "dns.hh"
44 #include "misc.hh"
45 #include "utility.hh"
46 #include "logger.hh"
47 #include "pdnsexception.hh"
48 #include "dnsrecords.hh"
49
50 class UeberBackend;
51 class DNSSECKeeper;
52
53
54 //! This class represents DNS packets, either received or to be sent.
55 class DNSPacket
56 {
57 public:
58 DNSPacket(bool isQuery);
59 DNSPacket(const DNSPacket &orig);
60
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
63 const string& getString(); //!< for serialization - just passes the whole packet
64
65 // address & socket manipulation
66 void setRemote(const ComboAddress*);
67 ComboAddress getRemote() const;
68 Netmask getRealRemote() const;
69 ComboAddress getLocal() const
70 {
71 ComboAddress ca;
72 socklen_t len=sizeof(ca);
73 getsockname(d_socket, (sockaddr*)&ca, &len);
74 return ca;
75 }
76 uint16_t getRemotePort() const;
77
78 boost::optional<ComboAddress> d_anyLocal;
79
80 Utility::sock_t getSocket() const
81 {
82 return d_socket;
83 }
84 void setSocket(Utility::sock_t sock);
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'
93
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')
98
99 /** Add a DNSZoneRecord to this packet. A DNSPacket (as does a DNS Packet) has 4 kinds of resource records. Questions,
100 Answers, Authority and Additional. See RFC 1034 and 1035 for details. You can specify where a record needs to go in the
101 DNSZoneRecord d_place field */
102 void addRecord(const DNSZoneRecord &); // adds to 'rrs'
103
104 void setQuestion(int op, const DNSName &qdomain, int qtype); // wipes 'd', sets a random id, creates start of packet (domain, type, class etc)
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
107 void wrapup(); // writes out queued rrs, and generates the binary packet. also shuffles. also rectifies dnsheader 'd', and copies it to the stringbuffer
108 void spoofQuestion(const DNSPacket *qd); //!< paste in the exact right case of the question. Useful for PacketCache
109 unsigned int getMinTTL(); //!< returns lowest TTL of any record in the packet
110 bool isEmpty(); //!< returns true if there are no rrs in the packet
111
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
114 void setCompress(bool compress);
115
116 DNSPacket *replyPacket() const; //!< convenience function that creates a virgin answer packet to this question
117
118 void commitD(); //!< copies 'd' into the stringbuffer
119 unsigned int getMaxReplyLen(); //!< retrieve the maximum length of the packet we should send in response
120 void setMaxReplyLen(int bytes); //!< set the max reply len (used when retrieving from the packet cache, and this changed)
121
122 bool couldBeCached(); //!< returns 0 if this query should bypass the packet cache
123 bool hasEDNSSubnet() const;
124 bool hasEDNS();
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; };
132 uint32_t getHash() const { return d_hash; };
133 void setHash(uint32_t hash) { d_hash = hash; };
134
135 //////// DATA !
136
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
140 string d_peer_principal;
141 const DNSName& getTSIGKeyname() const;
142
143 struct dnsheader d; //!< dnsheader at the start of the databuffer 12
144
145 TSIGRecordContent d_trc; //72
146
147 ComboAddress d_remote; //28
148 TSIGHashEnum d_tsig_algo{TSIG_MD5}; //4
149
150 int d_ednsRawPacketSizeLimit{-1}; // only used for Lua record
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};
157
158 bool getTSIGDetails(TSIGRecordContent* tr, DNSName* keyname, uint16_t* tsigPos=nullptr) const;
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;
161
162 vector<DNSZoneRecord>& getRRS() { return d_rrs; }
163 bool checkForCorrectTSIG(UeberBackend* B, DNSName* keyname, string* secret, TSIGRecordContent* trc) const;
164
165 static uint16_t s_udpTruncationThreshold;
166 static bool s_doEDNSSubnetProcessing;
167
168 private:
169 void pasteQ(const char *question, int length); //!< set the question of this packet, useful for crafting replies
170
171 string d_tsigsecret;
172 DNSName d_tsigkeyname;
173 string d_tsigprevious;
174
175 vector<DNSZoneRecord> d_rrs; // 8
176 std::unordered_set<size_t> d_dedup;
177 string d_rawpacket; // this is where everything lives 8
178 EDNSSubnetOpts d_eso;
179
180 int d_maxreplylen{0};
181 int d_socket{-1}; // 4
182 uint32_t d_hash{0};
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};
193 bool d_isQuery;
194 };
195
196 #endif