]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnswriter.hh
Merge pull request #3765 from pieterlexis/update-yahttp
[thirdparty/pdns.git] / pdns / dnswriter.hh
1 #ifndef PDNS_DNSWRITER_HH
2 #define PDNS_DNSWRITER_HH
3
4 #include <string>
5 #include <vector>
6 #include <map>
7 #include "dns.hh"
8 #include "dnsname.hh"
9 #include "namespaces.hh"
10 #include <arpa/inet.h>
11 /** this class can be used to write DNS packets. It knows about DNS in the sense that it makes
12 the packet header and record headers.
13
14 The model is:
15
16 packetheader (recordheader recordcontent)*
17
18 The packetheader needs to be updated with the amount of packets of each kind (answer, auth, additional)
19
20 Each recordheader contains the length of a dns record.
21
22 Calling convention:
23
24 vector<uint8_t> content;
25 DNSPacketWriter dpw(content, const string& qname, uint16_t qtype, uint16_t qclass=QClass:IN); // sets the question
26 dpw.startrecord("this.is.an.ip.address.", ns_t_a); // does nothing, except store qname and qtype
27 dpw.xfr32BitInt(0x01020304); // adds 4 bytes (0x01020304) to the record buffer
28 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
29 // new qname and qtype are stored
30 dpw.xfr32BitInt(0x04030201); // adds 4 bytes (0x04030201) to the record buffer
31 dpw.commit(); // writes out dnsrecord header containing qname and qtype and length 4, plus the recordbuffer
32
33 // content now contains the ready packet, with 1 question and 2 answers
34
35 */
36
37 class DNSPacketWriter : public boost::noncopyable
38 {
39
40 public:
41 typedef vector<pair<DNSName, uint16_t> > lmap_t;
42
43 //! Start a DNS Packet in the vector passed, with question qname, qtype and qclass
44 DNSPacketWriter(vector<uint8_t>& content, const DNSName& qname, uint16_t qtype, uint16_t qclass=QClass::IN, uint8_t opcode=0);
45
46 /** 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 -
47 ANSWER, AUTHORITY, ADDITIONAL */
48 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);
49
50 /** Shorthand way to add an Opt-record, for example for EDNS0 purposes */
51 typedef vector<pair<uint16_t,std::string> > optvect_t;
52 void addOpt(uint16_t udpsize, int extRCode, int Z, const optvect_t& options=optvect_t());
53
54 /** 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.
55 The content of the vector<> passed to the constructor is inconsistent until commit is called.
56 */
57 void commit();
58
59 uint32_t size(); // needs to be 32 bit because otherwise we don't see the wrap coming when it happened!
60
61 /** Should the packet have grown too big for the writer's liking, rollback removes the record currently being written */
62 void rollback();
63
64 /** Discard all content except the question section */
65 void truncate();
66
67 void xfr48BitInt(uint64_t val);
68 void xfr32BitInt(uint32_t val);
69 void xfr16BitInt(uint16_t val);
70 void xfrType(uint16_t val)
71 {
72 xfr16BitInt(val);
73 }
74 void xfrIP(const uint32_t& val)
75 {
76 xfr32BitInt(htonl(val));
77 }
78 void xfrIP6(const std::string& val)
79 {
80 xfrBlob(val,16);
81 }
82 void xfrTime(const uint32_t& val)
83 {
84 xfr32BitInt(val);
85 }
86
87 void xfr8BitInt(uint8_t val);
88
89 void xfrName(const DNSName& label, bool compress=false, bool noDot=false);
90 void xfrText(const string& text, bool multi=false, bool lenField=true);
91 void xfrUnquotedText(const string& text, bool lenField);
92 void xfrBlob(const string& blob, int len=-1);
93 void xfrBlobNoSpaces(const string& blob, int len=-1);
94 void xfrHexBlob(const string& blob, bool keepReading=false);
95
96 uint16_t d_pos;
97
98 dnsheader* getHeader();
99 void getRecords(string& records);
100 const vector<uint8_t>& getRecordBeingWritten() { return d_record; }
101
102 void setCanonic(bool val)
103 {
104 d_canonic=val;
105 }
106
107 void setLowercase(bool val)
108 {
109 d_lowerCase=val;
110 }
111 vector <uint8_t>& getContent()
112 {
113 return d_content;
114 }
115 bool eof() { return true; } // we don't know how long the record should be
116
117 private:
118 // We declare 1 uint_16 in the public section, these 3 align on a 8-byte boundry
119 uint16_t d_stuff;
120 uint16_t d_sor;
121 uint16_t d_rollbackmarker; // start of last complete packet, for rollback
122
123 vector <uint8_t>& d_content;
124 vector <uint8_t> d_record;
125 DNSName d_qname;
126 DNSName d_recordqname;
127 lmap_t d_labelmap;
128
129 uint32_t d_recordttl;
130 uint16_t d_recordqtype, d_recordqclass;
131
132 uint16_t d_truncatemarker; // end of header, for truncate
133 DNSResourceRecord::Place d_recordplace;
134 bool d_canonic, d_lowerCase;
135 };
136
137 typedef vector<pair<string::size_type, string::size_type> > labelparts_t;
138 // bool labeltokUnescape(labelparts_t& parts, const DNSName& label);
139 std::vector<string> segmentDNSText(const string& text); // from dnslabeltext.rl
140 std::deque<string> segmentDNSName(const string& input ); // from dnslabeltext.rl
141 #endif