File: dnswriter.hh

package info (click to toggle)
pdns-recursor 3.1.4-1
  • links: PTS
  • area: main
  • in suites: etch-m68k
  • size: 840 kB
  • ctags: 1,918
  • sloc: cpp: 9,746; ansic: 3,019; sh: 452; makefile: 123
file content (107 lines) | stat: -rw-r--r-- 3,706 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#ifndef PDNS_DNSWRITER_HH
#define PDNS_DNSWRITER_HH

#include <string>
#include <vector>
#include <map>
#if !defined SOLARIS8 && !defined WIN32
#include <stdint.h>
#elif defined WIN32
#include "utility.hh"
#endif
#include "dns.hh"
using namespace std;

/** this class can be used to write DNS packets. It knows about DNS in the sense that it makes 
    the packet header and record headers.

    The model is:

    packetheader (recordheader recordcontent)*

    The packetheader needs to be updated with the amount of packets of each kind (answer, auth, additional)
    
    Each recordheader contains the length of a dns record.

    Calling convention:

    vector<uint8_t> content;
    DNSPacketWriter dpw(content, const string& qname, uint16_t qtype, uint16_t qclass=1);  // sets the question
    dpw.startrecord("this.is.an.ip.address.", ns_t_a);    // does nothing, except store qname and qtype
    dpw.xfr32BitInt(0x01020304);                         // adds 4 bytes (0x01020304) to the record buffer
    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
                                                         // new qname and qtype are stored
    dpw.xfr32BitInt(0x04030201);                         // adds 4 bytes (0x04030201) to the record buffer
    dpw.commit();                                        // writes out dnsrecord header containing qname and qtype and length 4, plus the recordbuffer

    // content now contains the ready packet, with 1 question and 2 answers

*/

class DNSPacketWriter
{
public:
  enum Place {ANSWER=1, AUTHORITY=2, ADDITIONAL=3}; 

  //! Start a DNS Packet in the vector passed, with question qname, qtype and qclass
  DNSPacketWriter(vector<uint8_t>& content, const string& qname, uint16_t  qtype, uint16_t qclass=1);
  
  /** 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 - 
      ANSWER, AUTHORITY, ADDITIONAL */
  void startRecord(const string& name, uint16_t qtype, uint32_t ttl=3600, uint16_t qclass=1, Place place=ANSWER);

  /** Shorthand way to add an Opt-record, for example for EDNS0 purposes */
  void addOpt(int udpsize, int extRCode, int Z);

  /** 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.
      The content of the vector<> passed to the constructor is inconsistent until commit is called.
   */
  void commit();

  uint16_t size();

  /** Should the packet have grown too big for the writer's liking, rollback removes the record currently being written */
  void rollback();

  void xfr32BitInt(uint32_t val);
  void xfr16BitInt(uint16_t val);
  void xfrType(uint16_t val)
  {
    xfr16BitInt(val);
  }
  void xfrIP(const uint32_t& val)
  {
    xfr32BitInt(htonl(val));
  }
  void xfrTime(const uint32_t& val)
  {
    xfr32BitInt(val);
  }

  void xfr8BitInt(uint8_t val);

  void xfrLabel(const string& label, bool compress=false);
  void xfrText(const string& text);
  void xfrBlob(const string& blob);
  void xfrHexBlob(const string& blob);

  uint16_t d_pos;
  
  dnsheader* getHeader();
  void getRecords(string& records);

private:
  vector<uint8_t>& d_content;
  vector <uint8_t> d_record;
  string d_qname;
  uint16_t d_qtype, d_qclass;
  string d_recordqname;
  uint16_t d_recordqtype, d_recordqclass;
  uint32_t d_recordttl;
  map<string, uint16_t> d_labelmap;
  uint16_t d_stuff;
  uint16_t d_sor;
  uint16_t d_rollbackmarker; // start of last complete packet, for rollback
  Place d_recordplace;
};
#endif