Skip to content

Commit

Permalink
Major restyle to support response packets
Browse files Browse the repository at this point in the history
  • Loading branch information
crondaemon committed Sep 11, 2014
1 parent 9f0ceaa commit 167ae30
Show file tree
Hide file tree
Showing 14 changed files with 366 additions and 156 deletions.
9 changes: 5 additions & 4 deletions src/dns_header.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,12 @@ bool operator!=(const DnsHeaderFlags& f1, const DnsHeaderFlags& f2)
return !(f1 == f2);
}

void DnsHeader::parse(char* buf)
size_t DnsHeader::parse(char* buf, unsigned offset)
{
memcpy(&_txid, buf, 2);
memcpy(&_flags, buf + 2, 2);
memcpy(&_nRecord, buf + 4, 8);
memcpy(&_txid, buf + offset, 2);
memcpy(&_flags, buf + offset + 2, 2);
memcpy(&_nRecord, buf + offset + 4, 8);
return 12;
}

bool DnsHeader::rd() const
Expand Down
2 changes: 1 addition & 1 deletion src/dns_header.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class DnsHeader {
void fuzzTxid();
void fuzzNRecord(unsigned section);

void parse(char* buf);
size_t parse(char* buf, unsigned offset);
};

#endif
142 changes: 105 additions & 37 deletions src/dns_packet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ DnsPacket::DnsPacket()

_log = NULL;

_spoofing = false;

this->packets(0);
}

Expand Down Expand Up @@ -237,12 +239,34 @@ void DnsPacket::sendNet(bool doCksum)
_log(this->to_string());

if (send(_socket, output.data(), output.length(), 0) < 0) {
if (errno == 22) {
cout << "Invalid parameter (probably fuzzer is shaking it).\n";
if (_log && errno == 22) {
_log("Invalid parameter (probably fuzzer is shaking it)");
} else {
throw runtime_error("send() error: " + string(strerror(errno)));
}
}

if (!_spoofing) {
char buf[65535];
struct sockaddr_in addr;
socklen_t fromlen = sizeof(addr);
ssize_t bytes = recvfrom(_socket, buf, 65535, 0, (struct sockaddr*)&addr, &fromlen);
if (bytes == -1) {
throw runtime_error("Error in recvfrom(): " + string(strerror(errno)));
}
DnsPacket p;
p.parse(buf + sizeof(_ipHdr) + sizeof(_udpHdr));
struct iphdr* iph;
iph = (struct iphdr*)buf;

p.ipFrom(iph->saddr);
p.ipTo(iph->daddr);

if (_log)
_log(string("Received ") + p.to_string());

}

_datagrams--;
}

Expand Down Expand Up @@ -273,35 +297,39 @@ string DnsPacket::to_string(bool dnsonly) const
s += " ";
}

s += "txid: " + std::to_string(_dnsHdr.txid());
s += "txid: 0x" + Dines::toHex(_dnsHdr.txid());

s += isQuestion() ? " Q " : " R ";
s += "[Question:" + _question.to_string() + "]";
if (!_question.empty())
s += "[Question:" + _question.to_string() + "]";

if (_answers.size() > 0) {
s += "[Answers:";
for (vector<ResourceRecord>::const_iterator itr = _answers.begin();
itr != _answers.end(); ++itr) {
s += itr->to_string();
s += itr->to_string() + ",";
}
s.pop_back();
s += "]";
}

if (_authorities.size() > 0) {
s += "[Authorities:";
for (vector<ResourceRecord>::const_iterator itr = _authorities.begin();
itr != _authorities.end(); ++itr) {
s += itr->to_string();
s += itr->to_string() + ",";
}
s.pop_back();
s += "]";
}

if (_additionals.size() > 0) {
s += "[Additionals:";
for (vector<ResourceRecord>::const_iterator itr = _additionals.begin();
itr != _additionals.end(); ++itr) {
s += itr->to_string();
s += itr->to_string() + ",";
}
s.pop_back();
s += "]";
}

Expand Down Expand Up @@ -331,16 +359,43 @@ DnsQuestion& DnsPacket::addQuestion(const DnsQuestion& q)
return _question;
}

ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const ResourceRecord& rr, bool counter_increment)
{
std::vector<ResourceRecord> *rrPtr;

switch (section) {
case Dines::R_ANSWER:
rrPtr = &_answers;
break;
case Dines::R_AUTHORITIES:
rrPtr = &_authorities;
break;
case Dines::R_ADDITIONAL:
rrPtr = &_additionals;
break;
default:
throw runtime_error("Unexpected section " + std::to_string(section));
}

if (counter_increment)
_dnsHdr.nRecordAdd(section, 1);

rrPtr->push_back(rr);
isQuestion(false);
return rrPtr->front();
}

ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const std::string& rrDomain,
unsigned rrType, unsigned rrClass, unsigned ttl, const char* rdata, unsigned rdatalen)
unsigned rrType, unsigned rrClass, unsigned ttl, const char* rdata, unsigned rdatalen,
bool counter_increment)
{
string rd(rdata, rdatalen);
return addRR(section, rrDomain, rrType, rrClass, ttl, rd);
}

ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const std::string rrDomain,
const std::string& rrType, const std::string& rrClass, const std::string& ttl,
const std::string& rdata)
const std::string& rdata, bool counter_increment)
{
unsigned type = Dines::stringToQtype(rrType);
unsigned klass = Dines::stringToQclass(rrClass);
Expand All @@ -350,7 +405,7 @@ ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const std::string
}

ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const std::string& rrDomain,
unsigned rrType, unsigned rrClass, unsigned ttl, const std::string& rdata)
unsigned rrType, unsigned rrClass, unsigned ttl, const std::string& rdata, bool counter_increment)
{
ResourceRecord rr(rrDomain, rrType, rrClass, ttl, rdata);
return addRR(section, rr);
Expand Down Expand Up @@ -378,6 +433,7 @@ uint16_t DnsPacket::nRecord(Dines::RecordSection section) const

void DnsPacket::question(const DnsQuestion& q)
{
_dnsHdr.nRecord(Dines::R_QUESTION, 1);
_question = q;
}

Expand All @@ -401,8 +457,15 @@ const ResourceRecord& DnsPacket::authorities(unsigned n) const
return _authorities.at(n);
}

void DnsPacket::ipFrom(uint32_t ip)
{
_spoofing = true;
_ipHdr.saddr = ip;
}

void DnsPacket::ipFrom(string ip_from)
{
_spoofing = true;
_ipHdr.saddr = inet_addr(ip_from.data());
}

Expand All @@ -411,6 +474,12 @@ void DnsPacket::ipTo(string ip_to)
_ipHdr.daddr = inet_addr(ip_to.data());
}

void DnsPacket::ipTo(uint32_t ip)
{
_spoofing = true;
_ipHdr.daddr = ip;
}

uint16_t DnsPacket::sport() const
{
return ntohs(_udpHdr.source);
Expand Down Expand Up @@ -500,30 +569,6 @@ DnsHeader& DnsPacket::dnsHdr()
return _dnsHdr;
}

ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const ResourceRecord& rr)
{
std::vector<ResourceRecord> *rrPtr;

switch (section) {
case Dines::R_ANSWER:
rrPtr = &_answers;
break;
case Dines::R_AUTHORITIES:
rrPtr = &_authorities;
break;
case Dines::R_ADDITIONAL:
rrPtr = &_additionals;
break;
default:
throw runtime_error("Unexpected section " + std::to_string(section));
}

_dnsHdr.nRecordAdd(section, 1);
rrPtr->push_back(rr);
isQuestion(false);
return rrPtr->front();
}

void DnsPacket::fuzzSrcIp()
{
_fuzzSrcIp = true;
Expand Down Expand Up @@ -569,13 +614,36 @@ bool DnsPacket::invalid() const
string DnsPacket::invalidMsg() const
{
if (_ipHdr.daddr == 0)
return "You must specify destination ip (--dst-ip)";
return "You must specify destination ip";

return "";
}

void DnsPacket::parse(char* buf)
{
_dnsHdr.parse(buf);
_question.parse(buf + 12);
unsigned i;
unsigned offset = 0;
offset += _dnsHdr.parse(buf, offset);
offset += _question.parse(buf, offset);

// Parse answers
for (i = 0; i < _dnsHdr.nRecord(Dines::R_ANSWER); i++) {
ResourceRecord rr;
offset += rr.parse(buf, offset);
this->addRR(Dines::R_ANSWER, rr, false);
}

// Parse auth
for (i = 0; i < _dnsHdr.nRecord(Dines::R_AUTHORITIES); i++) {
ResourceRecord rr;
offset += rr.parse(buf, offset);
this->addRR(Dines::R_AUTHORITIES, rr, false);
}

// Parse add
for (i = 0; i < _dnsHdr.nRecord(Dines::R_ADDITIONAL); i++) {
ResourceRecord rr;
offset += rr.parse(buf, offset);
this->addRR(Dines::R_ADDITIONAL, rr, false);
}
}
15 changes: 10 additions & 5 deletions src/dns_packet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
class DnsPacket {
int _socket;
int _recvSocket;
bool _spoofing;

//! Creates the socket
void _socketCreate();
Expand Down Expand Up @@ -77,8 +78,10 @@ class DnsPacket {
std::string to_string(bool dnsonly = false) const;

void ipFrom(std::string ip_from);
void ipFrom(uint32_t ip);

void ipTo(std::string ip_to);
void ipTo(uint32_t ip);

//! IP source as string
std::string ipFrom() const;
Expand Down Expand Up @@ -128,19 +131,21 @@ class DnsPacket {
//! Adds a RR
ResourceRecord& addRR(Dines::RecordSection section, const std::string rrDomain,
const std::string& rrType, const std::string& rrClass, const std::string& ttl,
const std::string& rdata);
const std::string& rdata, bool counter_increment = true);

//! Adds a RR
ResourceRecord& addRR(Dines::RecordSection section, const std::string& rrDomain,
unsigned rrType, unsigned rrClass, unsigned ttl, const std::string& rdata);
unsigned rrType, unsigned rrClass, unsigned ttl, const std::string& rdata,
bool counter_increment = true);

//! Adds a RR
ResourceRecord& addRR(Dines::RecordSection section, const std::string& rrDomain,
unsigned rrType, unsigned rrClass, unsigned ttl, const char* rdata,
unsigned rdatalen);
unsigned rdatalen, bool counter_increment= true);

//! Adds a RR
ResourceRecord& addRR(Dines::RecordSection section, const ResourceRecord& rr);
ResourceRecord& addRR(Dines::RecordSection section, const ResourceRecord& rr,
bool counter_increment = true);

//! Run the fuzzer
void fuzz();
Expand Down Expand Up @@ -169,7 +174,7 @@ class DnsPacket {
//! Return a message that describe why a packet is invalid, empty string otherwise
std::string invalidMsg() const;

//! Parse a message from a buffer
//! Parse a message from a buffer. The buffer must point to the start of the dns packet
void parse(char* buf);
};

Expand Down
30 changes: 8 additions & 22 deletions src/dns_question.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,29 +170,15 @@ string DnsQuestion::to_string() const
return _qdomain_str + "/" + qtypeStr() + "/" + qclassStr();
}

void DnsQuestion::parse(char* buf)
{
unsigned i = 0;
while (buf[i] != 0)
i++;
i++;
_qdomain_enc = string(buf, i);

// Now parse the domain into printable form
_qdomain_str = "";
int cur = 1;
int len = buf[0];
while (len != 0) {
_qdomain_str += string(buf + cur, len);
_qdomain_str += ".";
cur += len;
len = buf[cur];
cur++;
}
_qdomain_str.erase(_qdomain_str.size() - 1, _qdomain_str.size());
size_t DnsQuestion::parse(char* buf, unsigned offset)
{
unsigned i;

i = Dines::domainDecode(buf, offset, _qdomain_enc, _qdomain_str);

memcpy(&_qtype, buf + i, 2);
memcpy(&_qclass, buf + i + 2, 2);
memcpy(&_qtype, buf + offset + i, 2);
memcpy(&_qclass, buf + offset + i + 2, 2);
return (_qdomain_enc.size() + 4);
}

bool DnsQuestion::empty() const
Expand Down
2 changes: 1 addition & 1 deletion src/dns_question.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class DnsQuestion {

std::string to_string() const;

void parse(char* buf);
size_t parse(char* buf, unsigned offset = 0);

bool empty() const;

Expand Down
Loading

0 comments on commit 167ae30

Please sign in to comment.