summaryrefslogtreecommitdiff
path: root/test/dns-proto.h
blob: 346711dfe9419ad6f2f14c0b94710c6b37a878a7 (plain)
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
// -*- mode: c++ -*-
#ifndef DNS_PROTO_H
#define DNS_PROTO_H
// Utilities for processing DNS packet contents

// Include ares internal file for DNS protocol constants
#include "nameser.h"

#include <memory>
#include <string>
#include <vector>

namespace ares {

typedef unsigned char byte;

std::string HexDump(std::vector<byte> data);
std::string HexDump(const byte *data, int len);
std::string HexDump(const char *data, int len);

std::string StatusToString(int status);
std::string RcodeToString(int rcode);
std::string RRTypeToString(int rrtype);
std::string ClassToString(int qclass);
std::string AddressToString(const void* addr, int len);

// Convert DNS protocol data to strings.
// Note that these functions are not defensive; they assume
// a validly formatted input, and so should not be used on
// externally-determined inputs.
std::string PacketToString(const std::vector<byte>& packet);
std::string QuestionToString(const std::vector<byte>& packet,
                             const byte** data, int* len);
std::string RRToString(const std::vector<byte>& packet,
                       const byte** data, int* len);


// Manipulate DNS protocol data.
void PushInt32(std::vector<byte>* data, int value);
void PushInt16(std::vector<byte>* data, int value);
std::vector<byte> EncodeString(const std::string& name);

struct DNSQuestion {
  DNSQuestion(const std::string& name, ns_type rrtype, ns_class qclass)
    : name_(name), rrtype_(rrtype), qclass_(qclass) {}
  DNSQuestion(const std::string& name, ns_type rrtype)
    : name_(name), rrtype_(rrtype), qclass_(ns_c_in) {}
  virtual ~DNSQuestion() {}
  virtual std::vector<byte> data() const;
  std::string name_;
  ns_type rrtype_;
  ns_class qclass_;
};

struct DNSRR : public DNSQuestion {
  DNSRR(const std::string& name, ns_type rrtype, ns_class qclass, int ttl)
    : DNSQuestion(name, rrtype, qclass), ttl_(ttl) {}
  DNSRR(const std::string& name, ns_type rrtype, int ttl)
    : DNSQuestion(name, rrtype), ttl_(ttl) {}
  virtual ~DNSRR() {}
  virtual std::vector<byte> data() const = 0;
  int ttl_;
};

struct DNSAddressRR : public DNSRR {
  DNSAddressRR(const std::string& name, ns_type rrtype, int ttl,
               const byte* addr, int addrlen)
    : DNSRR(name, rrtype, ttl), addr_(addr, addr + addrlen) {}
  DNSAddressRR(const std::string& name, ns_type rrtype, int ttl,
               const std::vector<byte>& addr)
    : DNSRR(name, rrtype, ttl), addr_(addr) {}
  virtual std::vector<byte> data() const;
  std::vector<byte> addr_;
};

struct DNSARR : public DNSAddressRR {
  DNSARR(const std::string& name, int ttl, const byte* addr, int addrlen)
    : DNSAddressRR(name, ns_t_a, ttl, addr, addrlen) {}
  DNSARR(const std::string& name, int ttl, const std::vector<byte>& addr)
    : DNSAddressRR(name, ns_t_a, ttl, addr) {}
};

struct DNSAaaaRR : public DNSAddressRR {
  DNSAaaaRR(const std::string& name, int ttl, const byte* addr, int addrlen)
    : DNSAddressRR(name, ns_t_aaaa, ttl, addr, addrlen) {}
  DNSAaaaRR(const std::string& name, int ttl, const std::vector<byte>& addr)
    : DNSAddressRR(name, ns_t_aaaa, ttl, addr) {}
};

struct DNSSingleNameRR : public DNSRR {
  DNSSingleNameRR(const std::string& name, ns_type rrtype, int ttl,
                  const std::string& other)
    : DNSRR(name, rrtype, ttl), other_(other) {}
  virtual std::vector<byte> data() const;
  std::string other_;
};

struct DNSCnameRR : public DNSSingleNameRR {
  DNSCnameRR(const std::string& name, int ttl, const std::string& other)
    : DNSSingleNameRR(name, ns_t_cname, ttl, other) {}
};

struct DNSNsRR : public DNSSingleNameRR {
  DNSNsRR(const std::string& name, int ttl, const std::string& other)
    : DNSSingleNameRR(name, ns_t_ns, ttl, other) {}
};

struct DNSPtrRR : public DNSSingleNameRR {
  DNSPtrRR(const std::string& name, int ttl, const std::string& other)
    : DNSSingleNameRR(name, ns_t_ptr, ttl, other) {}
};

struct DNSTxtRR : public DNSRR {
  DNSTxtRR(const std::string& name, int ttl, const std::vector<std::string>& txt)
    : DNSRR(name, ns_t_txt, ttl), txt_(txt) {}
  virtual std::vector<byte> data() const;
  std::vector<std::string> txt_;
};

struct DNSMxRR : public DNSRR {
  DNSMxRR(const std::string& name, int ttl, int pref, const std::string& other)
    : DNSRR(name, ns_t_mx, ttl), pref_(pref), other_(other) {}
  virtual std::vector<byte> data() const;
  int pref_;
  std::string other_;
};

struct DNSSrvRR : public DNSRR {
  DNSSrvRR(const std::string& name, int ttl,
           int prio, int weight, int port, const std::string& target)
    : DNSRR(name, ns_t_srv, ttl), prio_(prio), weight_(weight), port_(port), target_(target) {}
  virtual std::vector<byte> data() const;
  int prio_;
  int weight_;
  int port_;
  std::string target_;
};

struct DNSSoaRR : public DNSRR {
  DNSSoaRR(const std::string& name, int ttl,
           const std::string& nsname, const std::string& rname,
           int serial, int refresh, int retry, int expire, int minimum)
    : DNSRR(name, ns_t_soa, ttl), nsname_(nsname), rname_(rname),
      serial_(serial), refresh_(refresh), retry_(retry),
      expire_(expire), minimum_(minimum) {}
  virtual std::vector<byte> data() const;
  std::string nsname_;
  std::string rname_;
  int serial_;
  int refresh_;
  int retry_;
  int expire_;
  int minimum_;
};

struct DNSNaptrRR : public DNSRR {
  DNSNaptrRR(const std::string& name, int ttl,
             int order, int pref,
             const std::string& flags,
             const std::string& service,
             const std::string& regexp,
             const std::string& replacement)
    : DNSRR(name, ns_t_naptr, ttl), order_(order), pref_(pref),
      flags_(flags), service_(service), regexp_(regexp), replacement_(replacement) {}
  virtual std::vector<byte> data() const;
  int order_;
  int pref_;
  std::string flags_;
  std::string service_;
  std::string regexp_;
  std::string replacement_;
};

struct DNSOption {
  int code_;
  std::vector<byte> data_;
};

struct DNSOptRR : public DNSRR {
  DNSOptRR(int extrcode, int udpsize)
    : DNSRR("", ns_t_opt, static_cast<ns_class>(udpsize), extrcode) {}
  virtual std::vector<byte> data() const;
  std::vector<DNSOption> opts_;
};

struct DNSPacket {
  DNSPacket()
    : qid_(0), response_(false), opcode_(ns_o_query),
      aa_(false), tc_(false), rd_(false), ra_(false),
      z_(false), ad_(false), cd_(false), rcode_(ns_r_noerror) {}
  // Convenience functions that take ownership of given pointers.
  DNSPacket& add_question(DNSQuestion *q) {
    questions_.push_back(std::unique_ptr<DNSQuestion>(q));
    return *this;
  }
  DNSPacket& add_answer(DNSRR *q) {
    answers_.push_back(std::unique_ptr<DNSRR>(q));
    return *this;
  }
  DNSPacket& add_auth(DNSRR *q) {
    auths_.push_back(std::unique_ptr<DNSRR>(q));
    return *this;
  }
  DNSPacket& add_additional(DNSRR *q) {
    adds_.push_back(std::unique_ptr<DNSRR>(q));
    return *this;
  }
  // Chainable setters.
  DNSPacket& set_qid(int qid) { qid_ = qid; return *this; }
  DNSPacket& set_response(bool v = true) { response_ = v; return *this; }
  DNSPacket& set_aa(bool v = true) { aa_ = v; return *this; }
  DNSPacket& set_tc(bool v = true) { tc_ = v; return *this; }
  DNSPacket& set_rd(bool v = true) { rd_ = v; return *this; }
  DNSPacket& set_ra(bool v = true) { ra_ = v; return *this; }
  DNSPacket& set_z(bool v = true) { z_ = v; return *this; }
  DNSPacket& set_ad(bool v = true) { ad_ = v; return *this; }
  DNSPacket& set_cd(bool v = true) { cd_ = v; return *this; }
  DNSPacket& set_rcode(ns_rcode rcode) { rcode_ = rcode; return *this; }

  // Return the encoded packet.
  std::vector<byte> data() const;

  int qid_;
  bool response_;
  ns_opcode opcode_;
  bool aa_;
  bool tc_;
  bool rd_;
  bool ra_;
  bool z_;
  bool ad_;
  bool cd_;
  ns_rcode rcode_;
  std::vector<std::unique_ptr<DNSQuestion>> questions_;
  std::vector<std::unique_ptr<DNSRR>> answers_;
  std::vector<std::unique_ptr<DNSRR>> auths_;
  std::vector<std::unique_ptr<DNSRR>> adds_;
};

}  // namespace ares

#endif