74
83
DNSPacket(const DNSPacket &orig);
76
int expand(const unsigned char *begin, const unsigned char *end, string &expanded, int depth=0);
77
inline int parse(const char *mesg, int len); //!< parse a raw UDP or TCP packet and suck the data inward
80
//! the raw DNS header
83
unsigned int id:16; //!< id of this query/response
84
#ifdef WORDS_BIGENDIAN // ultrasparc
85
unsigned int qr:1; //!< 1 if this is a query, 0 if response
86
unsigned int opcode:4; //!< the opcode
87
unsigned int aa:1; //!< packet contains authoritative data
88
unsigned int tc:1; //!< packet is truncated
89
unsigned int rd:1; //!< this packets wants us to recurse
90
unsigned int ra:1; //!< ??
91
unsigned int unused:1; //!<
92
unsigned int ad:1; //!< authentic data
93
unsigned int cd:1; //!< checking disabled by resolver
94
unsigned int rcode:4; //!< ??
96
unsigned int rd:1; //!< this packets wants us to recurse
97
unsigned int tc:1; //!< packet is truncated
98
unsigned int aa:1; //!< packet contains authoritative data
99
unsigned int opcode:4; //!< the opcode
100
unsigned int qr:1; //!< 1 if this is a query, 0 if response
104
unsigned int rcode:4; //!< ??
105
unsigned int cd:1; //!< checking disabled by resolver
106
unsigned int ad:1; //!< authentic data
107
unsigned int unused:1; //!<
108
unsigned int ra:1; //!< ??
112
unsigned int qdcount:16; //!< number of questions
113
unsigned int ancount:16; //!< number of answers
114
unsigned int nscount:16; //!< number of authoritative nameservers included in answer
115
unsigned int arcount:16; //!< number of additional resource records
118
inline void setRemote(const struct sockaddr *a, Utility::socklen_t socklen);
119
string getLocal() const;
85
int parse(const char *mesg, int len); //!< parse a raw UDP or TCP packet and suck the data inward
86
string getString(); //!< for serialization - just passes the whole packet
88
// address & socket manipulation
89
void setRemote(const ComboAddress*);
120
90
string getRemote() const;
91
string getLocal() const
94
socklen_t len=sizeof(ca);
95
getsockname(d_socket, (sockaddr*)&ca, &len);
121
98
uint16_t getRemotePort() const;
122
void setA(bool); //!< make this packet authoritative
123
void setRA(bool); //!< set the Recursion Available flag
124
void setRD(bool); //!< set the Recursion Desired flag
125
void setAnswer(bool); //!< Make this packet an answer
126
void setID(uint16_t); //!< set the DNS id of this packet
127
void setOpcode(uint16_t); //!< set the Opcode of this packet
128
void setRcode(int v); //!< set the Rcode of this packet
100
Utility::sock_t getSocket() const
104
void setSocket(Utility::sock_t sock);
107
// these manipulate 'd'
108
void setA(bool); //!< make this packet authoritative - manipulates 'd'
109
void setID(uint16_t); //!< set the DNS id of this packet - manipulates 'd'
110
void setRA(bool); //!< set the Recursion Available flag - manipulates 'd'
111
void setRD(bool); //!< set the Recursion Desired flag - manipulates 'd'
112
void setAnswer(bool); //!< Make this packet an answer - clears the 'stringbuffer' first, if passed 'true', does nothing otherwise, manipulates 'd'
114
void setOpcode(uint16_t); //!< set the Opcode of this packet - manipulates 'd'
115
void setRcode(int v); //!< set the Rcode of this packet - manipulates 'd'
117
void clearRecords(); //!< when building a packet, wipe all previously added records (clears 'rrs')
131
119
/** Add a DNSResourceRecord to this packet. A DNSPacket (as does a DNS Packet) has 4 kinds of resource records. Questions,
132
120
Answers, Authority and Additional. See RFC 1034 and 1035 for details. You can specify where a record needs to go in the
133
121
DNSResourceRecord d_place field */
134
void addRecord(const DNSResourceRecord &);
136
/** helper function for both DNSPacket and addSOARecord() - converts a line into a struct, for easier parsing */
137
static void fillSOAData(const string &content, SOAData &data);
139
/** for use by DNSPacket, converts a SOAData class to a ascii line again */
140
static string serializeSOAData(const SOAData &data);
141
void setQuestion(int op, const string &qdomain, int qtype);
142
vector<DNSResourceRecord> getAnswers();
144
string compress(const string &qd);
145
void addARecord(const string&, uint32_t, uint32_t ttl, DNSResourceRecord::Place place); //!< add an A record to the packet
146
void addARecord(const DNSResourceRecord &); //!< add an A record to the packet
148
void addAAAARecord(const string &, unsigned char addr[16], uint32_t ttl, DNSResourceRecord::Place place); //!< add an A record to the packet
149
void addAAAARecord(const DNSResourceRecord &); //!< add an A record to the packet
152
void addMXRecord(const string &domain, const string &mx, int priority, uint32_t ttl); //!< add an MX record to the packet
153
void addMXRecord(const DNSResourceRecord &); //!< add an MX record to the packet
155
void addSRVRecord(const string &domain, const string &srv, int priority, uint32_t ttl); //!< add an SRVMX record to the packet
156
void addSRVRecord(const DNSResourceRecord &); //!< add an SRV record to the packet
158
void addCNAMERecord(const string &domain, const string &alias, uint32_t ttl); //!< add a CNAME record to the packet
159
void addCNAMERecord(const DNSResourceRecord &); //!< add a CNAME record to the packet
161
void addRPRecord(const string &domain, const string &content, uint32_t ttl); //!< add a RP record to the packet
162
void addRPRecord(const DNSResourceRecord &); //!< add a RP record to the packet
164
void addNAPTRRecord(const string &domain, const string &content, uint32_t ttl); //!< add a NAPTR record to the packet
165
void addNAPTRRecord(const DNSResourceRecord &); //!< add a NAPTR record to the packet
168
void addPTRRecord(const string &domain, const string &alias, uint32_t ttl); //!< add a PTR record to the packet
169
void addPTRRecord(const DNSResourceRecord &); //!< add a PTR record to the packet
171
void addLOCRecord(const string &domain, const string &content, uint32_t ttl);
172
void addLOCRecord(const DNSResourceRecord &); //!< add a LOC record to the packet
175
/** Adds a SOA record to the packet. The SOA record is very special because we have a lot of default values,
176
that may be overridden by the contents of the database. Content can have a variety of content:
180
hostmaster serial-number
181
hostmaster serial-number [refresh [retry [expire [ minimum] ] ] ]
183
Suggested values are:
185
10800 ;refresh every three hours
186
300 ;retry every 5 min
187
604800 ;expire after a week
190
An empty field means that we supply hostmaster+@+domain name as hostmaster. An empty serial number is replaced by the
191
number of seconds since 1 jan 1970 (unix timestamp). The other values are substituted as indicated
194
void addSOARecord(const string &domain, const string &content, uint32_t ttl, DNSResourceRecord::Place place);
195
void addSOARecord(const DNSResourceRecord &); //!< add a SOA record to the packet
197
void addTXTorSPFRecord(uint16_t qtype, string domain, string, uint32_t ttl); //!< add a TXT or SPF record to the packet
199
void addTXTRecord(const DNSResourceRecord &); //!< add a TXT record to the packet
200
void addSPFRecord(const DNSResourceRecord &); //!< add a SPF record to the packet
202
void addHINFORecord(string domain, string, uint32_t ttl); //!< add a HINFO record to the packet
203
void addHINFORecord(const DNSResourceRecord &); //!< add a HINFO record to the packet
205
void addNSRecord(string domain, string server, uint32_t ttl, DNSResourceRecord::Place place); //!< add an NS record to the packet
206
void addNSRecord(const DNSResourceRecord &); //!< add an NS record to the packet
207
void addGenericRecord(const DNSResourceRecord& rr);
208
static string &attodot(string &str); //!< for when you need to insert an email address in the SOA
122
void addRecord(const DNSResourceRecord &); // adds to 'rrs'
124
void setQuestion(int op, const string &qdomain, int qtype); // wipes 'd', sets a random id, creates start of packet (label, type, class etc)
212
126
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
213
void pasteQ(const char *question, int length); //!< set the question of this packet, useful for crafting replies
216
inline const char *getData(void); //!< get binary representation of packet
217
void setRaw(char *mesg, int length);
218
const char *getRaw(void);
219
inline void spoofID(uint16_t id); //!< change the ID of an existing packet. Useful for fixing up packets returned from the PacketCache
220
inline void spoofQuestion(const string &qd); //!< paste in the exact right case of the question. Useful for PacketCache
127
void wrapup(void); // writes out queued rrs, and generates the binary packet. also shuffles. also rectifies dnsheader 'd', and copies it to the stringbuffer
128
const char *getData(void); //!< get binary representation of packet, will call 'wrapup' for you
130
const char *getRaw(void); //!< provides access to the raw packet, possibly on a packet that has never been 'wrapped'
131
void spoofID(uint16_t id); //!< change the ID of an existing packet. Useful for fixing up packets returned from the PacketCache
132
void spoofQuestion(const string &qd); //!< paste in the exact right case of the question. Useful for PacketCache
221
133
void truncate(int new_length); // has documentation in source
223
bool needAP(); //!< query this to find out if this packet needs additional processing
224
135
vector<DNSResourceRecord*> getAPRecords(); //!< get a vector with DNSResourceRecords that need additional processing
225
136
void setCompress(bool compress);
227
138
DNSPacket *replyPacket() const; //!< convenience function that creates a virgin answer packet to this question
228
Utility::sock_t getSocket() const
232
inline void setSocket(Utility::sock_t sock);
233
inline void commitD();
234
static bool isRD(const string &buffer)
236
return ((struct dnsheader *)buffer.c_str())->rd;
140
void commitD(); //!< copies 'd' into the stringbuffer
241
char remote[sizeof(sockaddr_in6)];
242
Utility::socklen_t d_socklen; // 4
243
145
uint16_t len; //!< length of the raw binary packet 2
244
146
uint16_t qclass; //!< class of the question - should always be INternet 2
245
147
struct dnsheader d; //!< dnsheader at the start of the databuffer 12
247
149
QType qtype; //!< type of the question 8
249
string qdomain; //!< qname of the question 4
151
string qdomain; //!< qname of the question 4 - unsure how this is used
155
void pasteQ(const char *question, int length); //!< set the question of this packet, useful for crafting replies
252
157
bool d_wrapped; // 1
253
158
bool d_compress; // 1
254
159
uint16_t d_qlen; // length of the question (including class & type) in this packet 2
256
161
int d_socket; // 4
258
int findlabel(string &label);
259
int toqname(const char *name, string &qname, bool compress = true);
260
int toqname(const string &name, string &qname, bool compress = true);
261
int toqname(const string &name, string *qname, bool compress = true);
262
const string makeSoaHostmasterPiece(const string &hostmaster);
263
static string parseLOC(const unsigned char *p, unsigned int length);
264
void makeHeader(char *p,uint16_t qtype, uint32_t ttl);
270
163
string stringbuffer; // this is where everything lives 4
276
inline void DNSPacket::spoofQuestion(const string &qd)
278
string label=compress(qd);
279
for(string::size_type i=0;i<label.size();++i)
280
stringbuffer[i+sizeof(d)]=label[i];
281
d_wrapped=true; // if we do this, don't later on wrapup
284
/** This function takes data from the network, possibly received with recvfrom, and parses
285
it into our class. Results of calling this function multiple times on one packet are
286
unknown. Returns -1 if the packet cannot be parsed.
288
int DNSPacket::parse(const char *mesg, int length)
290
stringbuffer.assign(mesg,length);
293
L << Logger::Warning << "Ignoring packet: too short from "
294
<< getRemote() << endl;
298
memcpy((void *)&d,(const void *)stringbuffer.c_str(),12);
303
if(!ntohs(d.qdcount)) {
305
L << Logger::Warning << "No question section in packet from " << getRemote() <<", rcode="<<(int)d.rcode<<endl;
310
offset = getq(); // also sets this->qdomain!
311
d_qlen=offset+4; // this points to the start of any answers
314
// L << Logger::Warning << "Ignoring packet: invalid label in question from "
315
// << inet_ntoa(remote.sin_addr) << endl;
318
if(qdomain.length() > 255) { // this prevents crap from the rootservers
324
if((unsigned int)(15+offset)>=stringbuffer.length()) {
325
L << Logger::Warning << "Ignoring packet: question too short from "<< getRemote()<<", offset "<<
326
15+offset<<">="<<stringbuffer.length()<<endl;
330
qtype=((unsigned char)stringbuffer[12+offset])*256+(unsigned char)stringbuffer[13+offset];
331
qclass=((unsigned char)stringbuffer[14+offset]*256)+(unsigned char)stringbuffer[15+offset];
335
//! Use this to set where this packet was received from or should be sent to
336
inline void DNSPacket::setRemote(const struct sockaddr *s, Utility::socklen_t socklen)
338
if(socklen>(Utility::socklen_t)sizeof(remote))
339
throw AhuException("Address too long for storage: "+itoa(socklen));
341
memcpy((void *)remote,(void *)s,socklen);
345
inline void DNSPacket::spoofID(uint16_t id)
347
stringbuffer[1]=(id>>8)&0xff;
348
stringbuffer[0]=id&0xff;
352
inline void DNSPacket::setSocket(Utility::sock_t sock)
357
inline void DNSPacket::commitD()
359
stringbuffer.replace(0,12,(char *)&d,12); // copy in d
362
inline const char *DNSPacket::getData(void)
367
return stringbuffer.data();