add a lot of Doxygen comments

This commit is contained in:
bert hubert 2018-04-17 14:19:44 +02:00
parent 602f8a6cad
commit ea5194dc80
9 changed files with 2610 additions and 73 deletions

2493
tdns/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,12 @@
#include "sclasses.hh" #include "sclasses.hh"
using namespace std; using namespace std;
/*!
@file
@brief Actual zone contents can be put / retrieved from this file
*/
//! Called by tdns.cc main() to load user content
void loadZones(DNSNode& zones) void loadZones(DNSNode& zones)
{ {
auto addresses=resolveName("f.root-servers.net"); // this retrieves IPv4 and IPv6 auto addresses=resolveName("f.root-servers.net"); // this retrieves IPv4 and IPv6

View File

@ -11,6 +11,52 @@
#include "nenum.hh" #include "nenum.hh"
#include "comboaddress.hh" #include "comboaddress.hh"
/*!
@file
@brief Defines DNSLabel, DNSType, DNSClass and DNSNode, which together store DNS details
*/
// note - some platforms are confused over these #defines. Specifically, BYTE_ORDER without __ is a false prophet and may lie!
//! DNS header struct
struct dnsheader {
unsigned id :16; /* query identification number */
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* fields in third byte */
unsigned qr: 1; /* response flag */
unsigned opcode: 4; /* purpose of message */
unsigned aa: 1; /* authoritative answer */
unsigned tc: 1; /* truncated message */
unsigned rd: 1; /* recursion desired */
/* fields in fourth byte */
unsigned ra: 1; /* recursion available */
unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
unsigned ad: 1; /* authentic data from named */
unsigned cd: 1; /* checking disabled by resolver */
unsigned rcode :4; /* response code */
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
/* fields in third byte */
unsigned rd :1; /* recursion desired */
unsigned tc :1; /* truncated message */
unsigned aa :1; /* authoritative answer */
unsigned opcode :4; /* purpose of message */
unsigned qr :1; /* response flag */
/* fields in fourth byte */
unsigned rcode :4; /* response code */
unsigned cd: 1; /* checking disabled by resolver */
unsigned ad: 1; /* authentic data from named */
unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
unsigned ra :1; /* recursion available */
#endif
/* remaining bytes */
uint16_t qdcount; /* number of question entries */
uint16_t ancount; /* number of answer entries */
uint16_t nscount; /* number of authority entries */
uint16_t arcount; /* number of resource entries */
};
static_assert(sizeof(dnsheader) == 12, "dnsheader size must be 12");
// enums // enums
enum class RCode enum class RCode
{ {
@ -39,10 +85,10 @@ enum class DNSClass : uint16_t
}; };
SMARTENUMSTART(DNSClass) SENUM2(DNSClass, IN, CHAOS) SMARTENUMEND(DNSClass) SMARTENUMSTART(DNSClass) SENUM2(DNSClass, IN, CHAOS) SMARTENUMEND(DNSClass)
COMBOENUM4(DNSSection, Question, 0, Answer, 1, Authority, 2, Additional, 3) COMBOENUM4(DNSSection, Question, 0, Answer, 1, Authority, 2, Additional, 3);
// this semicolon makes Doxygen happy
/*! \brief Represents a DNS label, which is part of a DNS Name */
//! Represents a DNS label, which is part of a DNS Name
class DNSLabel class DNSLabel
{ {
public: public:
@ -109,9 +155,9 @@ DNSName operator+(const DNSName& a, const DNSName& b);
class DNSMessageWriter; class DNSMessageWriter;
/* this is the how all resource records are stored, as generators /*! this is the how all resource records are stored, as generators
that can convert their content to a human readable string or to a DNSMessage * that can convert their content to a human readable string or to a DNSMessage
*/ */
struct RRGen struct RRGen
{ {
virtual void toMessage(DNSMessageWriter& dpw) = 0; virtual void toMessage(DNSMessageWriter& dpw) = 0;
@ -119,7 +165,7 @@ struct RRGen
virtual DNSType getType() const = 0; virtual DNSType getType() const = 0;
}; };
/* Resource records are treated as a set and have one TTL for the whole set */ //! Resource records are treated as a set and have one TTL for the whole set
struct RRSet struct RRSet
{ {
std::vector<std::unique_ptr<RRGen>> contents; std::vector<std::unique_ptr<RRGen>> contents;
@ -130,7 +176,7 @@ struct RRSet
uint32_t ttl{3600}; uint32_t ttl{3600};
}; };
/* A node in the DNS tree */ //! A node in the DNS tree
struct DNSNode struct DNSNode
{ {
~DNSNode(); ~DNSNode();
@ -140,23 +186,24 @@ struct DNSNode
//! This is an idempotent way to add a node to a DNS tree //! This is an idempotent way to add a node to a DNS tree
DNSNode* add(DNSName name); DNSNode* add(DNSName name);
// add one or more generators to this node //! add one RRGen to this node
void addRRs(std::unique_ptr<RRGen>&&a); void addRRs(std::unique_ptr<RRGen>&&a);
//! add multiple RRGen to this node
template<typename... Types> template<typename... Types>
void addRRs(std::unique_ptr<RRGen>&&a, Types&&... args) void addRRs(std::unique_ptr<RRGen>&&a, Types&&... args)
{ {
addRRs(std::move(a)); addRRs(std::move(a));
addRRs(std::forward<Types>(args)...); addRRs(std::forward<Types>(args)...);
} }
//! Walk the tree and visit each node
void visit(std::function<void(const DNSName& name, const DNSNode*)> visitor, DNSName name) const; void visit(std::function<void(const DNSName& name, const DNSNode*)> visitor, DNSName name) const;
// children, found by DNSLabel //! children, found by DNSLabel
std::map<DNSLabel, DNSNode> children; std::map<DNSLabel, DNSNode> children;
// the RRSets, grouped by type // !the RRSets, grouped by type
std::map<DNSType, RRSet > rrsets; std::map<DNSType, RRSet > rrsets;
std::unique_ptr<DNSNode> zone; // if this is set, this node is a zone std::unique_ptr<DNSNode> zone; //!< if this is set, this node is a zone
uint16_t namepos{0}; //!< for label compression, we also use DNSNodes uint16_t namepos{0}; //!< for label compression, we also use DNSNodes
}; };

View File

@ -1,40 +0,0 @@
#pragma once
#include <stdint.h>
// note - some platforms are confused over these #defines. Specifically, BYTE_ORDER without __ is a false prophet and may lie!
struct dnsheader {
unsigned id :16; /* query identification number */
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* fields in third byte */
unsigned qr: 1; /* response flag */
unsigned opcode: 4; /* purpose of message */
unsigned aa: 1; /* authoritative answer */
unsigned tc: 1; /* truncated message */
unsigned rd: 1; /* recursion desired */
/* fields in fourth byte */
unsigned ra: 1; /* recursion available */
unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
unsigned ad: 1; /* authentic data from named */
unsigned cd: 1; /* checking disabled by resolver */
unsigned rcode :4; /* response code */
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
/* fields in third byte */
unsigned rd :1; /* recursion desired */
unsigned tc :1; /* truncated message */
unsigned aa :1; /* authoritative answer */
unsigned opcode :4; /* purpose of message */
unsigned qr :1; /* response flag */
/* fields in fourth byte */
unsigned rcode :4; /* response code */
unsigned cd: 1; /* checking disabled by resolver */
unsigned ad: 1; /* authentic data from named */
unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
unsigned ra :1; /* recursion available */
#endif
/* remaining bytes */
uint16_t qdcount; /* number of question entries */
uint16_t ancount; /* number of answer entries */
uint16_t nscount; /* number of authority entries */
uint16_t arcount; /* number of resource entries */
};
static_assert(sizeof(dnsheader) == 12, "dnsheader size must be 12");

View File

@ -1,10 +1,14 @@
#pragma once #pragma once
#include "dns.hh"
#include "dns-storage.hh" #include "dns-storage.hh"
#include "record-types.hh" #include "record-types.hh"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <vector> #include <vector>
/*!
@file
@brief Defines DNSMessageReader and DNSMessageWriter
*/
//! A class that parses a DNS Message //! A class that parses a DNS Message
class DNSMessageReader class DNSMessageReader
{ {
@ -20,37 +24,45 @@ public:
//! Returns true if there was an EDNS record, plus copies details //! Returns true if there was an EDNS record, plus copies details
bool getEDNS(uint16_t* newsize, bool* doBit) const; bool getEDNS(uint16_t* newsize, bool* doBit) const;
//! Puts the next RR in content, unless at 'end of message', in which case it returns false
bool getRR(DNSSection& section, DNSName& name, DNSType& type, uint32_t& ttl, std::unique_ptr<RRGen>& content); bool getRR(DNSSection& section, DNSName& name, DNSType& type, uint32_t& ttl, std::unique_ptr<RRGen>& content);
void skipRRs(int n); //!< Skip over n RRs void skipRRs(int n); //!< Skip over n RRs
uint8_t d_ednsVersion{0}; uint8_t d_ednsVersion{0};
void xfrName(DNSName& ret, uint16_t* pos=0); void xfrName(DNSName& ret, uint16_t* pos=0); //!< put the next name in ret, or copy it from pos
//! Convenience form of xfrName that returns its result
DNSName getName(uint16_t* pos=0) { DNSName res; xfrName(res, pos); return res;} DNSName getName(uint16_t* pos=0) { DNSName res; xfrName(res, pos); return res;}
//! Gets the next 8 bit unsigned integer from the message, or the one from 'pos'
void xfrUInt8(uint8_t&res, uint16_t* pos = 0) void xfrUInt8(uint8_t&res, uint16_t* pos = 0)
{ {
if(!pos) pos = &payloadpos; if(!pos) pos = &payloadpos;
res=payload.at((*pos)++); res=payload.at((*pos)++);
} }
uint8_t getUInt8(uint16_t* pos=0) //! Convenience form that returns the next 8 bit integer, or from pos
uint8_t getUInt8(uint16_t* pos=0)
{ uint8_t ret; xfrUInt8(ret, pos); return ret; } { uint8_t ret; xfrUInt8(ret, pos); return ret; }
//! Gets the next 16 bit unsigned integer from the message
void xfrUInt16(uint16_t& res) void xfrUInt16(uint16_t& res)
{ {
memcpy(&res, &payload.at(payloadpos+1)-1, 2); memcpy(&res, &payload.at(payloadpos+1)-1, 2);
payloadpos+=2; payloadpos+=2;
res=htons(res); res=htons(res);
} }
//! Convenience form that returns the next 16 bit integer
uint16_t getUInt16() uint16_t getUInt16()
{ uint16_t ret; xfrUInt16(ret); return ret; } { uint16_t ret; xfrUInt16(ret); return ret; }
//! Gets the next 32 bit unsigned integer from the message
void xfrUInt32(uint32_t& res) void xfrUInt32(uint32_t& res)
{ {
memcpy(&res, &payload.at(payloadpos+3)-3, 4); memcpy(&res, &payload.at(payloadpos+3)-3, 4);
payloadpos+=4; payloadpos+=4;
res=ntohl(res); res=ntohl(res);
} }
//! Gets the next size bytes from the message, of from pos
void xfrBlob(std::string& blob, int size, uint16_t* pos = 0) void xfrBlob(std::string& blob, int size, uint16_t* pos = 0)
{ {
if(!pos) pos = &payloadpos; if(!pos) pos = &payloadpos;
@ -62,6 +74,7 @@ public:
(*pos) += size; (*pos) += size;
} }
//! Convenience function that returns next size bytes of the message, or from pos
std::string getBlob(int size, uint16_t* pos = 0) std::string getBlob(int size, uint16_t* pos = 0)
{ {
std::string res; std::string res;

View File

@ -1,7 +1,12 @@
#include "record-types.hh" #include "record-types.hh"
#include <iomanip> #include <iomanip>
/* this exploits the similarity in writing/reading DNS messages /*!
@file
@brief Defines has the actual Resource Record Generators
*/
/*! this exploits the similarity in writing/reading DNS messages
and outputting master file format text */ and outputting master file format text */
struct StringBuilder struct StringBuilder
{ {
@ -24,7 +29,6 @@ struct StringBuilder
std::string& d_string; std::string& d_string;
}; };
AGen::AGen(DNSMessageReader& x) AGen::AGen(DNSMessageReader& x)
{ {
x.xfrUInt32(d_ip); x.xfrUInt32(d_ip);

View File

@ -6,7 +6,10 @@
class DNSMessageReader; class DNSMessageReader;
/* /*!
@file
@brief Defines all Resource Record Generators
Generators know about a record type's contents. Generators know about a record type's contents.
They also know how to inject themselves into a DNSMessageWriter, parse themselves from a DNSMessageReader They also know how to inject themselves into a DNSMessageWriter, parse themselves from a DNSMessageReader
and how to convert themselves into a master file representation. and how to convert themselves into a master file representation.
@ -30,7 +33,7 @@ struct AGen : RRGen
uint32_t d_ip; // the actual IP uint32_t d_ip; // the actual IP
}; };
//! Generates an AAAA (IPv6 address) record
struct AAAAGen : RRGen struct AAAAGen : RRGen
{ {
AAAAGen(DNSMessageReader& dmr); AAAAGen(DNSMessageReader& dmr);
@ -50,6 +53,7 @@ struct AAAAGen : RRGen
unsigned char d_ip[16]; unsigned char d_ip[16];
}; };
//! Generates a SOA Resource Record
struct SOAGen : RRGen struct SOAGen : RRGen
{ {
SOAGen(const DNSName& mname, const DNSName& rname, uint32_t serial, uint32_t minimum=3600, uint32_t refresh=10800, uint32_t retry=3600, uint32_t expire=604800) : SOAGen(const DNSName& mname, const DNSName& rname, uint32_t serial, uint32_t minimum=3600, uint32_t refresh=10800, uint32_t retry=3600, uint32_t expire=604800) :
@ -71,6 +75,7 @@ struct SOAGen : RRGen
uint32_t d_serial, d_minimum, d_refresh, d_retry, d_expire; uint32_t d_serial, d_minimum, d_refresh, d_retry, d_expire;
}; };
//! Generates a CNAME Resource Record
struct CNAMEGen : RRGen struct CNAMEGen : RRGen
{ {
CNAMEGen(const DNSName& name) : d_name(name) {} CNAMEGen(const DNSName& name) : d_name(name) {}
@ -86,6 +91,7 @@ struct CNAMEGen : RRGen
DNSName d_name; DNSName d_name;
}; };
//! Generates a PTR Resource Record
struct PTRGen : RRGen struct PTRGen : RRGen
{ {
PTRGen(const DNSName& name) : d_name(name) {} PTRGen(const DNSName& name) : d_name(name) {}
@ -100,6 +106,7 @@ struct PTRGen : RRGen
DNSName d_name; DNSName d_name;
}; };
//! Generates an NS Resource Record
struct NSGen : RRGen struct NSGen : RRGen
{ {
NSGen(const DNSName& name) : d_name(name) {} NSGen(const DNSName& name) : d_name(name) {}
@ -114,7 +121,7 @@ struct NSGen : RRGen
DNSName d_name; DNSName d_name;
}; };
//! Generates an MX Resource Record
struct MXGen : RRGen struct MXGen : RRGen
{ {
MXGen(uint16_t prio, const DNSName& name) : d_prio(prio), d_name(name) {} MXGen(uint16_t prio, const DNSName& name) : d_prio(prio), d_name(name) {}
@ -131,6 +138,7 @@ struct MXGen : RRGen
DNSName d_name; DNSName d_name;
}; };
//! Generates an TXT Resource Record
struct TXTGen : RRGen struct TXTGen : RRGen
{ {
TXTGen(const std::string& txt) : d_txt(txt) {} TXTGen(const std::string& txt) : d_txt(txt) {}
@ -144,7 +152,7 @@ struct TXTGen : RRGen
std::string d_txt; std::string d_txt;
}; };
/* This implements 'unknown record types' */ //! This implements 'unknown record types'
struct UnknownGen : RRGen struct UnknownGen : RRGen
{ {
UnknownGen(DNSType type, const std::string& rr) : d_type(type), d_rr(rr) {} UnknownGen(DNSType type, const std::string& rr) : d_type(type), d_rr(rr) {}
@ -155,6 +163,7 @@ struct UnknownGen : RRGen
DNSType getType() const override { return d_type; } DNSType getType() const override { return d_type; }
}; };
//! This implements a fun dynamic TXT record type
struct ClockTXTGen : RRGen struct ClockTXTGen : RRGen
{ {
ClockTXTGen(const std::string& format) : d_format(format) {} ClockTXTGen(const std::string& format) : d_format(format) {}

View File

@ -3,11 +3,16 @@
#include <map> #include <map>
#include <stdexcept> #include <stdexcept>
#include "sclasses.hh" #include "sclasses.hh"
#include "dns.hh"
#include <thread> #include <thread>
#include <signal.h> #include <signal.h>
#include "record-types.hh" #include "record-types.hh"
/*!
@file
@brief Tiny 'dig'-like utility to create DNS queries & print responses
*/
using namespace std; using namespace std;
DNSName fromString(const std::string& str) DNSName fromString(const std::string& str)

View File

@ -11,7 +11,6 @@
#include <map> #include <map>
#include <stdexcept> #include <stdexcept>
#include "sclasses.hh" #include "sclasses.hh"
#include "dns.hh"
#include <thread> #include <thread>
#include <signal.h> #include <signal.h>
#include "record-types.hh" #include "record-types.hh"
@ -261,7 +260,9 @@ catch(std::out_of_range& e) { // exceeded packet size
cout<<"\tAdditional records would have overflowed the packet, stopped adding them, not truncating yet\n"; cout<<"\tAdditional records would have overflowed the packet, stopped adding them, not truncating yet\n";
} }
/* helper function which encapsulates a DNS message within an 'envelope' /*! \brief Writes a DNSMessageWriter to a TCP/IP socket, with length envelope
helper function which encapsulates a DNS message within an 'envelope'
Note that it is highly recommended to send the envelope (with length) Note that it is highly recommended to send the envelope (with length)
as a single call. This saves packets and works around implementation bugs as a single call. This saves packets and works around implementation bugs
over at resolvers */ over at resolvers */
@ -274,7 +275,7 @@ static void writeTCPMessage(int sock, DNSMessageWriter& response)
SWriten(sock, ser); SWriten(sock, ser);
} }
/* helper to read a 16 bit length in network order. Returns 0 on EOF */ /*! helper to read a 16 bit length in network order. Returns 0 on EOF */
uint16_t tcpGetLen(int sock) uint16_t tcpGetLen(int sock)
{ {
string message = SRead(sock, 2); string message = SRead(sock, 2);
@ -288,7 +289,7 @@ uint16_t tcpGetLen(int sock)
return htons(len); return htons(len);
} }
/* spawned for each new TCP/IP client. In actual production this is not a good idea */ /*! spawned for each new TCP/IP client. In actual production this is not a good idea. */
void tcpClientThread(ComboAddress remote, int s, const DNSNode* zones) void tcpClientThread(ComboAddress remote, int s, const DNSNode* zones)
{ {
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
@ -387,7 +388,7 @@ void tcpClientThread(ComboAddress remote, int s, const DNSNode* zones)
} }
} }
//! connects to remote, retrieves a zone, returns it as a smart pointer //! connects to an authoritative server, retrieves a zone, returns it as a smart pointer
std::unique_ptr<DNSNode> retrieveZone(const ComboAddress& remote, const DNSName& zone) std::unique_ptr<DNSNode> retrieveZone(const ComboAddress& remote, const DNSName& zone)
{ {
cout<<"Attempting to retrieve zone "<<zone<<" from "<<remote.toStringWithPort()<<endl; cout<<"Attempting to retrieve zone "<<zone<<" from "<<remote.toStringWithPort()<<endl;
@ -435,6 +436,7 @@ std::unique_ptr<DNSNode> retrieveZone(const ComboAddress& remote, const DNSName&
return ret; return ret;
} }
//! This is the main tdns function
int main(int argc, char** argv) int main(int argc, char** argv)
try try
{ {
@ -444,8 +446,6 @@ try
} }
cout<<"Hello and welcome to tdns, the teaching authoritative nameserver"<<endl; cout<<"Hello and welcome to tdns, the teaching authoritative nameserver"<<endl;
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
ComboAddress local(argv[1], 53); ComboAddress local(argv[1], 53);