| 1 | #include "dnswriter.hh" |
|---|
| 2 | #include "misc.hh" |
|---|
| 3 | #include "dnsparser.hh" |
|---|
| 4 | |
|---|
| 5 | static const string EncodeDNSLabel(const string& input) |
|---|
| 6 | { |
|---|
| 7 | typedef vector<string> parts_t; |
|---|
| 8 | parts_t parts; |
|---|
| 9 | stringtok(parts,input,"."); |
|---|
| 10 | |
|---|
| 11 | string ret; |
|---|
| 12 | for(parts_t::const_iterator i=parts.begin(); i!=parts.end(); ++i) { |
|---|
| 13 | ret.append(1, (char)i->length()); |
|---|
| 14 | ret.append(*i); |
|---|
| 15 | } |
|---|
| 16 | ret.append(1,(char)0); |
|---|
| 17 | return ret; |
|---|
| 18 | } |
|---|
| 19 | |
|---|
| 20 | DNSPacketWriter::DNSPacketWriter(vector<uint8_t>& content, const string& qname, uint16_t qtype, uint16_t qclass) |
|---|
| 21 | : d_pos(0), d_content(content), d_qname(qname), d_qtype(qtype), d_qclass(qclass) |
|---|
| 22 | { |
|---|
| 23 | d_content.clear(); |
|---|
| 24 | dnsheader dnsheader; |
|---|
| 25 | |
|---|
| 26 | memset(&dnsheader, 0, sizeof(dnsheader)); |
|---|
| 27 | dnsheader.id=random(); |
|---|
| 28 | dnsheader.qdcount=htons(1); |
|---|
| 29 | |
|---|
| 30 | const uint8_t* ptr=(const uint8_t*)&dnsheader; |
|---|
| 31 | d_content.insert(d_content.end(), ptr, ptr + sizeof(dnsheader)); |
|---|
| 32 | |
|---|
| 33 | string label=EncodeDNSLabel(d_qname); |
|---|
| 34 | ptr=(const uint8_t*) label.c_str(); |
|---|
| 35 | d_content.insert(d_content.end(), ptr, ptr + label.length()); |
|---|
| 36 | |
|---|
| 37 | qtype=htons(qtype); |
|---|
| 38 | ptr=(const uint8_t*)&qtype; |
|---|
| 39 | d_content.insert(d_content.end(), ptr, ptr+2); |
|---|
| 40 | |
|---|
| 41 | qclass=htons(qclass); |
|---|
| 42 | ptr=(const uint8_t*)&qclass; |
|---|
| 43 | d_content.insert(d_content.end(), ptr, ptr+2); |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | void DNSPacketWriter::startRecord(const string& name, uint16_t qtype, uint16_t qclass) |
|---|
| 47 | { |
|---|
| 48 | if(!d_record.empty()) |
|---|
| 49 | commit(); |
|---|
| 50 | d_recordqname=name; |
|---|
| 51 | d_recordqtype=qtype; |
|---|
| 52 | d_recordqclass=qclass; |
|---|
| 53 | |
|---|
| 54 | dnsheader* dh=(dnsheader*) &*d_content.begin(); |
|---|
| 55 | dh->ancount = htons(ntohs(dh->ancount) + 1); |
|---|
| 56 | } |
|---|
| 57 | |
|---|
| 58 | void DNSPacketWriter::xfr32BitInt(uint32_t val) |
|---|
| 59 | { |
|---|
| 60 | uint8_t* ptr=reinterpret_cast<uint8_t*>(&val); |
|---|
| 61 | d_record.insert(d_record.end(), ptr, ptr+4); |
|---|
| 62 | } |
|---|
| 63 | |
|---|
| 64 | void DNSPacketWriter::xfr16BitInt(uint16_t val) |
|---|
| 65 | { |
|---|
| 66 | uint8_t* ptr=reinterpret_cast<uint8_t*>(&val); |
|---|
| 67 | d_record.insert(d_record.end(), ptr, ptr+2); |
|---|
| 68 | } |
|---|
| 69 | |
|---|
| 70 | void DNSPacketWriter::xfr8BitInt(uint8_t val) |
|---|
| 71 | { |
|---|
| 72 | d_record.push_back(val); |
|---|
| 73 | } |
|---|
| 74 | |
|---|
| 75 | void DNSPacketWriter::xfrText(const string& text) |
|---|
| 76 | { |
|---|
| 77 | d_record.push_back(text.length()); |
|---|
| 78 | const uint8_t* ptr=(uint8_t*)(text.c_str()); |
|---|
| 79 | d_record.insert(d_record.end(), ptr, ptr+text.size()); |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | void DNSPacketWriter::xfrLabel(const string& label) |
|---|
| 83 | { |
|---|
| 84 | string encoded=EncodeDNSLabel(label); |
|---|
| 85 | const uint8_t* ptr=reinterpret_cast<const uint8_t*>(encoded.c_str()); |
|---|
| 86 | |
|---|
| 87 | d_record.insert(d_record.end(), ptr, ptr+encoded.size()); |
|---|
| 88 | } |
|---|
| 89 | |
|---|
| 90 | void DNSPacketWriter::xfrBlob(const string& blob) |
|---|
| 91 | { |
|---|
| 92 | const uint8_t* ptr=reinterpret_cast<const uint8_t*>(blob.c_str()); |
|---|
| 93 | |
|---|
| 94 | d_record.insert(d_record.end(), ptr, ptr+blob.size()); |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | |
|---|
| 98 | void DNSPacketWriter::commit() |
|---|
| 99 | { |
|---|
| 100 | string label=EncodeDNSLabel(d_qname); // write out qname |
|---|
| 101 | |
|---|
| 102 | const uint8_t* ptr=(const uint8_t*) label.c_str(); |
|---|
| 103 | d_content.insert(d_content.end(), ptr, ptr + label.length()); |
|---|
| 104 | |
|---|
| 105 | // write out dnsrecordheader |
|---|
| 106 | struct dnsrecordheader drh; |
|---|
| 107 | drh.d_type=htons(d_recordqtype); |
|---|
| 108 | drh.d_class=htons(d_recordqclass); |
|---|
| 109 | drh.d_ttl=htonl(3600); |
|---|
| 110 | drh.d_clen=htons(d_record.size()); |
|---|
| 111 | |
|---|
| 112 | ptr=(const uint8_t*)&drh; |
|---|
| 113 | d_content.insert(d_content.end(), ptr, ptr+sizeof(drh)); |
|---|
| 114 | |
|---|
| 115 | // write out d_record |
|---|
| 116 | d_content.insert(d_content.end(), d_record.begin(), d_record.end()); |
|---|
| 117 | |
|---|
| 118 | d_record.clear(); // clear d_record |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | |
|---|
| 122 | |
|---|
| 123 | |
|---|
| 124 | |
|---|
| 125 | |
|---|