class UnknownRecordContent : public DNSRecordContent
{
public:
- UnknownRecordContent(const struct dnsrecordheader& ah, PacketReader& pr)
- : d_ah(ah)
+ UnknownRecordContent(const DNSRecord& dr, PacketReader& pr)
+ : d_dr(dr)
{
- pr.copyRecord(d_record, ah.d_clen);
+ pr.copyRecord(d_record, dr.d_clen);
}
- string getType() const
- {
- return "#"+lexical_cast<string>(d_ah.d_type);
- }
-
-
-
string getZoneRepresentation() const
{
ostringstream str;
- if(d_ah.d_class==1)
+ if(d_dr.d_class==1)
str<<"IN";
else
- str<<"CLASS"<<d_ah.d_class;
+ str<<"CLASS"<<d_dr.d_class;
str<<"\t";
- str<<"TYPE"<<d_ah.d_type<<"\t";
+ str<<"TYPE"<<d_dr.d_type<<"\t";
str<<"\\# "<<d_record.size()<<" ";
char hex[4];
private:
- struct dnsrecordheader d_ah;
+ const DNSRecord& d_dr;
vector<u_int8_t> d_record;
};
-DNSRecordContent* DNSRecordContent::mastermake(const struct dnsrecordheader& ah,
+DNSRecordContent* DNSRecordContent::mastermake(const DNSRecord &dr,
PacketReader& pr)
{
- typemap_t::const_iterator i=typemap.find(make_pair(ah.d_class, ah.d_type));
+ typemap_t::const_iterator i=typemap.find(make_pair(dr.d_class, dr.d_type));
if(i==typemap.end()) {
- return new UnknownRecordContent(ah, pr);
+ return new UnknownRecordContent(dr, pr);
}
- return i->second(ah, pr);
+ return i->second(dr, pr);
}
DNSRecordContent::typemap_t DNSRecordContent::typemap __attribute__((init_priority(1000)));
+DNSRecordContent::namemap_t DNSRecordContent::namemap __attribute__((init_priority(1000)));
void MOADNSParser::init(const char *packet, unsigned int len)
{
dr.d_class=ah.d_class;
dr.d_label=label;
- dr.d_ah=ah;
+ dr.d_clen=ah.d_clen;
d_answers.push_back(make_pair(dr, pr.d_pos));
- dr.d_content=boost::shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(ah, pr));
+ dr.d_content=boost::shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(dr, pr));
if(dr.d_content) {
// cout<<dr.d_label<<"\t"<<dr.d_content->getZoneRepresentation();
}
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <boost/shared_ptr.hpp>
+#include <boost/lexical_cast.hpp>
namespace {
typedef HEADER dnsheader;
class MOADNSParser;
+
+
class PacketReader
{
public:
};
+class DNSRecord;
+
class DNSRecordContent
{
public:
- static DNSRecordContent* mastermake(const struct dnsrecordheader& ah, PacketReader& pr);
+ static DNSRecordContent* mastermake(const DNSRecord &dr, PacketReader& pr);
virtual std::string getZoneRepresentation() const = 0;
- virtual std::string getType() const=0;
virtual ~DNSRecordContent() {}
std::string label;
struct dnsrecordheader header;
+
+ typedef DNSRecordContent* makerfunc_t(const struct DNSRecord& dr, PacketReader& pr);
+ static void regist(uint16_t cl, uint16_t ty, makerfunc_t* f, const char* name)
+ {
+ typemap[make_pair(cl,ty)]=f;
+ namemap[make_pair(cl,ty)]=name;
+ }
+
+ static uint16_t TypeToNumber(const string& name)
+ {
+ for(namemap_t::const_iterator i=namemap.begin(); i!=namemap.end();++i)
+ if(i->second==name)
+ return i->first.second;
+
+ throw runtime_error("Unknown DNS type '"+name+"'");
+
+ }
+
+ static const string NumberToType(uint16_t num)
+ {
+ if(!namemap.count(make_pair(1,num)))
+ throw runtime_error("Unknown DNS type with numerical id "+lexical_cast<string>(num));
+ return namemap[make_pair(1,num)];
+ }
+
+
protected:
- typedef DNSRecordContent* makerfunc_t(const struct dnsrecordheader& ah, PacketReader& pr);
+
typedef std::map<std::pair<u_int16_t, u_int16_t>, makerfunc_t* > typemap_t;
static typemap_t typemap;
+ typedef std::map<std::pair<u_int16_t, u_int16_t>, string > namemap_t;
+ static namemap_t namemap;
};
struct DNSRecord
u_int16_t d_type;
u_int16_t d_class;
u_int32_t d_ttl;
+ u_int16_t d_clen;
enum {Answer, Nameserver, Additional} d_place;
boost::shared_ptr<DNSRecordContent> d_content;
- struct dnsrecordheader d_ah;
};
+
class MOADNSParser
{
public:
dnsheader d_header;
string d_qname;
u_int16_t d_qclass, d_qtype;
+ uint8_t d_rcode;
typedef vector<pair<DNSRecord, uint16_t > > answers_t;
answers_t d_answers;
using namespace std;
using namespace boost;
-
class ARecordContent : public DNSRecordContent
{
public:
static void report(void)
{
- typemap[make_pair(1,1)]=&make;
- }
+ regist(1,1,&make,"A");
+ }
- static DNSRecordContent* make(const struct dnsrecordheader& ah, PacketReader& pr)
+ static DNSRecordContent* make(const DNSRecord& dr, PacketReader& pr)
{
- if(ah.d_clen!=4)
+ if(dr.d_clen!=4)
throw MOADNSException("Wrong size for A record");
ARecordContent* ret=new ARecordContent();
return d_ip;
}
- string getType() const
- {
- return "A";
- }
string getZoneRepresentation() const
{
typemap[make_pair(1,ns_t_aaaa)]=&make;
}
- string getType() const
- {
- return "AAAA";
- }
-
-
- static DNSRecordContent* make(const struct dnsrecordheader& ah, PacketReader& pr)
+ static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr)
{
- if(ah.d_clen!=16)
+ if(dr.d_clen!=16)
throw MOADNSException("Wrong size for AAAA record");
AAAARecordContent* ret=new AAAARecordContent();
{
public:
- OneLabelRecordContent(const struct dnsrecordheader& ah, const string& nsname) : d_type(ah.d_type), d_nsname(nsname) {}
+ OneLabelRecordContent(const DNSRecord &dr, const string& nsname) : d_type(dr.d_type), d_nsname(nsname) {}
static void report(void)
{
- typemap[make_pair(1,ns_t_ns)]=&make;
- typemap[make_pair(1,ns_t_cname)]=&make;
- typemap[make_pair(1,ns_t_ptr)]=&make;
+ regist(1, ns_t_ns, &make, "NS");
+ regist(1, ns_t_cname, &make, "CNAME");
+ regist(1, ns_t_ptr, &make, "PTR");
}
- static DNSRecordContent* make(const struct dnsrecordheader& ah, PacketReader &pr)
+ static DNSRecordContent* make(const DNSRecord &dr, PacketReader &pr)
{
- return new OneLabelRecordContent(ah, pr.getLabel());
- }
-
- string getType() const
- {
- if(d_type==ns_t_ns)
- return "NS";
- else if(d_type==ns_t_cname)
- return "CNAME";
- if(d_type==ns_t_ptr)
- return "PTR";
+ return new OneLabelRecordContent(dr, pr.getLabel());
}
string getZoneRepresentation() const
static void report(void)
{
- typemap[make_pair(1,6)]=&make;
+ regist(1,ns_t_soa,&make,"SOA");
}
- string getType() const
- {
- return "SOA";
- }
-
-
- static DNSRecordContent* make(const struct dnsrecordheader& ah, PacketReader& pr)
+ static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr)
{
u_int16_t nowpos(pr.d_pos);
string mname=pr.getLabel();
string rname=pr.getLabel();
- u_int16_t left=ah.d_clen - (pr.d_pos-nowpos);
+ u_int16_t left=dr.d_clen - (pr.d_pos-nowpos);
if(left!=sizeof(struct soatimes))
throw MOADNSException("SOA RDATA has wrong size: "+lexical_cast<string>(left)+ ", should be "+lexical_cast<string>(sizeof(struct soatimes)));
{
}
- string getType() const
- {
- return "MX";
- }
-
-
static void report(void)
{
- typemap[make_pair(1,ns_t_mx)]=&make;
+ regist(1,ns_t_mx,&make,"MX");
}
- static DNSRecordContent* make(const struct dnsrecordheader& ah, PacketReader& pr)
+ static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr)
{
u_int16_t preference=pr.get16BitInt();
string mxname=pr.getLabel();
OneLabelRecordContent::report();
SOARecordContent::report();
MXRecordContent::report();
+ MXRecordContent::regist(1,255,0,"ANY");
}
} reporter __attribute__((init_priority(65535)));
int main(int argc, char** argv)
try
{
- DNSPacketGenerator dpg(argv[3], atoi(argv[4]));
+ DNSPacketGenerator dpg(argv[3], DNSRecordContent::TypeToNumber(argv[4]));
Socket sock(InterNetwork, Datagram);
- IPEndpoint dest(argv[1], atoi(argv[2]));
+ IPEndpoint dest(argv[1] + (*argv[1]=='@'), atoi(argv[2]));
sock.sendTo(dpg.getPacket(), dest);
string reply;
sock.recvFrom(reply, dest);
MOADNSParser mdp(reply);
- cout<<"Reply to question for qname='"<<mdp.d_qname<<"', qtype="<<mdp.d_qtype<<endl;
-
+ cout<<"Reply to question for qname='"<<mdp.d_qname<<"', qtype="<<DNSRecordContent::NumberToType(mdp.d_qtype)<<endl;
+ cout<<"Rcode: "<<mdp.d_header.rcode<<", RA: "<<mdp.d_header.ra<<", RD: "<<mdp.d_header.rd;
+ cout<<", TC: "<<mdp.d_header.tc<<", AA: "<<mdp.d_header.aa<<", opcode: "<<mdp.d_header.opcode<<endl;
for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
shared_ptr<PacketReader> pr=mdp.getPacketReader(i->second);
- DNSRecordContent* drc=DNSRecordContent::mastermake(i->first.d_ah, *pr);
- cout<<i->first.d_place<<"\t"<<i->first.d_label<<"\tIN\t"<<drc->getType()<<"\t"<<i->first.d_ttl<<"\t"<<drc->getZoneRepresentation()<<endl;
+ DNSRecordContent* drc=DNSRecordContent::mastermake(i->first, *pr);
+ cout<<i->first.d_place<<"\t"<<i->first.d_label<<"\tIN\t"<<DNSRecordContent::NumberToType(i->first.d_type)<<"\t"<<i->first.d_ttl<<"\t"<<drc->getZoneRepresentation()<<endl;
}