]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnswriter.hh
Merge pull request #4547 from zeha/soaedit-cleanup
[thirdparty/pdns.git] / pdns / dnswriter.hh
CommitLineData
12471842
PL
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 */
a0a276c2
BH
22#ifndef PDNS_DNSWRITER_HH
23#define PDNS_DNSWRITER_HH
24
25#include <string>
26#include <vector>
bca6643b 27#include <map>
5a57d2ea 28#include "dns.hh"
4a51ff72 29#include "dnsname.hh"
10f4eea8 30#include "namespaces.hh"
1bc3ebb6 31#include <arpa/inet.h>
802a93d0 32
33
950cfe0f 34/** this class can be used to write DNS packets. It knows about DNS in the sense that it makes
a0a276c2
BH
35 the packet header and record headers.
36
37 The model is:
38
39 packetheader (recordheader recordcontent)*
40
41 The packetheader needs to be updated with the amount of packets of each kind (answer, auth, additional)
950cfe0f 42
a0a276c2
BH
43 Each recordheader contains the length of a dns record.
44
45 Calling convention:
46
47 vector<uint8_t> content;
703761cc 48 DNSPacketWriter dpw(content, const string& qname, uint16_t qtype, uint16_t qclass=QClass:IN); // sets the question
7738a23f 49 dpw.startrecord("this.is.an.ip.address.", ns_t_a); // does nothing, except store qname and qtype
a0a276c2 50 dpw.xfr32BitInt(0x01020304); // adds 4 bytes (0x01020304) to the record buffer
7738a23f 51 dpw.startrecord("this.is.an.ip.address.", ns_t_a); // aha! writes out dnsrecord header containing qname and qtype and length 4, plus the recordbuffer, which gets emptied
a0a276c2
BH
52 // new qname and qtype are stored
53 dpw.xfr32BitInt(0x04030201); // adds 4 bytes (0x04030201) to the record buffer
54 dpw.commit(); // writes out dnsrecord header containing qname and qtype and length 4, plus the recordbuffer
55
56 // content now contains the ready packet, with 1 question and 2 answers
57
58*/
59
f3f4938f 60class DNSPacketWriter : public boost::noncopyable
a0a276c2 61{
a2ce25e4 62
a0a276c2 63public:
bca6643b 64 //! Start a DNS Packet in the vector passed, with question qname, qtype and qclass
c2f3be9d 65 DNSPacketWriter(vector<uint8_t>& content, const DNSName& qname, uint16_t qtype, uint16_t qclass=QClass::IN, uint8_t opcode=0);
950cfe0f
PD
66
67 /** Start a new DNS record within this packet for namq, qtype, ttl, class and in the requested place. Note that packets can only be written in natural order -
bca6643b 68 ANSWER, AUTHORITY, ADDITIONAL */
e693ff5a 69 void startRecord(const DNSName& name, uint16_t qtype, uint32_t ttl=3600, uint16_t qclass=QClass::IN, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER, bool compress=true);
bca6643b
BH
70
71 /** Shorthand way to add an Opt-record, for example for EDNS0 purposes */
7f7b8d55 72 typedef vector<pair<uint16_t,std::string> > optvect_t;
bf269e28 73 void addOpt(uint16_t udpsize, int extRCode, int Z, const optvect_t& options=optvect_t(), uint8_t version=0);
a0a276c2 74
bca6643b
BH
75 /** needs to be called after the last record is added, but can be called again and again later on. Is called internally by startRecord too.
76 The content of the vector<> passed to the constructor is inconsistent until commit is called.
77 */
78 void commit();
79
dffbaa08 80 uint32_t size(); // needs to be 32 bit because otherwise we don't see the wrap coming when it happened!
10321a98
BH
81
82 /** Should the packet have grown too big for the writer's liking, rollback removes the record currently being written */
83 void rollback();
84
add935a2
PD
85 /** Discard all content except the question section */
86 void truncate();
87
341930bb 88 void xfr48BitInt(uint64_t val);
a0a276c2
BH
89 void xfr32BitInt(uint32_t val);
90 void xfr16BitInt(uint16_t val);
8bf26468
BH
91 void xfrType(uint16_t val)
92 {
93 xfr16BitInt(val);
94 }
cbf0e7f3
BH
95 void xfrIP(const uint32_t& val)
96 {
ea634573 97 xfr32BitInt(htonl(val));
cbf0e7f3 98 }
950cfe0f 99 void xfrIP6(const std::string& val)
b9b28916
AT
100 {
101 xfrBlob(val,16);
102 }
8bf26468
BH
103 void xfrTime(const uint32_t& val)
104 {
105 xfr32BitInt(val);
106 }
107
a0a276c2
BH
108 void xfr8BitInt(uint8_t val);
109
f21fc0aa 110 void xfrName(const DNSName& label, bool compress=false, bool noDot=false);
84e1142d 111 void xfrText(const string& text, bool multi=false, bool lenField=true);
948a927f 112 void xfrUnquotedText(const string& text, bool lenField);
06ffdc52 113 void xfrBlob(const string& blob, int len=-1);
2fe9d6f7 114 void xfrBlobNoSpaces(const string& blob, int len=-1);
e4090157 115 void xfrHexBlob(const string& blob, bool keepReading=false);
bca6643b 116
8e97e9a3 117 dnsheader* getHeader();
e636cab2 118 void getRecordPayload(string& records); // call __before commit__
ea634573 119
950cfe0f 120 void setCanonic(bool val)
f3f4938f
BH
121 {
122 d_canonic=val;
123 }
124
950cfe0f 125 void setLowercase(bool val)
7f5bf0ba
BH
126 {
127 d_lowerCase=val;
128 }
3f45f34d
BH
129 vector <uint8_t>& getContent()
130 {
131 return d_content;
132 }
d476d7fb 133 bool eof() { return true; } // we don't know how long the record should be
7f5bf0ba 134
a0a276c2 135private:
802a93d0 136 uint16_t lookupName(const DNSName& name, uint16_t* matchlen);
fea4599a 137 vector<uint16_t> d_namepositions;
78817f22 138 // We declare 1 uint_16 in the public section, these 3 align on a 8-byte boundry
78817f22
PL
139 uint16_t d_sor;
140 uint16_t d_rollbackmarker; // start of last complete packet, for rollback
141
57e5f5f7 142 vector <uint8_t>& d_content;
c2f3be9d 143 DNSName d_qname;
78817f22 144
add935a2 145 uint16_t d_truncatemarker; // end of header, for truncate
e693ff5a 146 DNSResourceRecord::Place d_recordplace;
7f5bf0ba 147 bool d_canonic, d_lowerCase;
a0a276c2 148};
213f6de6
BH
149
150typedef vector<pair<string::size_type, string::size_type> > labelparts_t;
c2f3be9d 151// bool labeltokUnescape(labelparts_t& parts, const DNSName& label);
bac8f21b 152std::vector<string> segmentDNSText(const string& text); // from dnslabeltext.rl
be6fbc68 153std::deque<string> segmentDNSName(const string& input ); // from dnslabeltext.rl
a0a276c2 154#endif