add a lot of Doxygen comments
This commit is contained in:
parent
602f8a6cad
commit
ea5194dc80
2493
tdns/Doxyfile
Normal file
2493
tdns/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,12 @@
|
||||
#include "sclasses.hh"
|
||||
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)
|
||||
{
|
||||
auto addresses=resolveName("f.root-servers.net"); // this retrieves IPv4 and IPv6
|
||||
|
@ -11,6 +11,52 @@
|
||||
#include "nenum.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
|
||||
enum class RCode
|
||||
{
|
||||
@ -39,10 +85,10 @@ enum class DNSClass : uint16_t
|
||||
};
|
||||
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
|
||||
|
||||
|
||||
//! Represents a DNS label, which is part of a DNS Name
|
||||
/*! \brief Represents a DNS label, which is part of a DNS Name */
|
||||
class DNSLabel
|
||||
{
|
||||
public:
|
||||
@ -109,9 +155,9 @@ DNSName operator+(const DNSName& a, const DNSName& b);
|
||||
|
||||
class DNSMessageWriter;
|
||||
|
||||
/* 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
|
||||
*/
|
||||
/*! 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
|
||||
*/
|
||||
struct RRGen
|
||||
{
|
||||
virtual void toMessage(DNSMessageWriter& dpw) = 0;
|
||||
@ -119,7 +165,7 @@ struct RRGen
|
||||
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
|
||||
{
|
||||
std::vector<std::unique_ptr<RRGen>> contents;
|
||||
@ -130,7 +176,7 @@ struct RRSet
|
||||
uint32_t ttl{3600};
|
||||
};
|
||||
|
||||
/* A node in the DNS tree */
|
||||
//! A node in the DNS tree
|
||||
struct DNSNode
|
||||
{
|
||||
~DNSNode();
|
||||
@ -140,23 +186,24 @@ struct DNSNode
|
||||
//! This is an idempotent way to add a node to a DNS tree
|
||||
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);
|
||||
//! add multiple RRGen to this node
|
||||
template<typename... Types>
|
||||
void addRRs(std::unique_ptr<RRGen>&&a, Types&&... args)
|
||||
{
|
||||
addRRs(std::move(a));
|
||||
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;
|
||||
|
||||
// children, found by DNSLabel
|
||||
//! children, found by DNSLabel
|
||||
std::map<DNSLabel, DNSNode> children;
|
||||
|
||||
// the RRSets, grouped by type
|
||||
// !the RRSets, grouped by type
|
||||
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
|
||||
};
|
||||
|
||||
|
40
tdns/dns.hh
40
tdns/dns.hh
@ -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");
|
@ -1,10 +1,14 @@
|
||||
#pragma once
|
||||
#include "dns.hh"
|
||||
#include "dns-storage.hh"
|
||||
#include "record-types.hh"
|
||||
#include <arpa/inet.h>
|
||||
#include <vector>
|
||||
|
||||
/*!
|
||||
@file
|
||||
@brief Defines DNSMessageReader and DNSMessageWriter
|
||||
*/
|
||||
|
||||
//! A class that parses a DNS Message
|
||||
class DNSMessageReader
|
||||
{
|
||||
@ -20,37 +24,45 @@ public:
|
||||
//! Returns true if there was an EDNS record, plus copies details
|
||||
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);
|
||||
void skipRRs(int n); //!< Skip over n RRs
|
||||
|
||||
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;}
|
||||
//! Gets the next 8 bit unsigned integer from the message, or the one from 'pos'
|
||||
void xfrUInt8(uint8_t&res, uint16_t* pos = 0)
|
||||
{
|
||||
if(!pos) pos = &payloadpos;
|
||||
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; }
|
||||
|
||||
|
||||
//! Gets the next 16 bit unsigned integer from the message
|
||||
void xfrUInt16(uint16_t& res)
|
||||
{
|
||||
memcpy(&res, &payload.at(payloadpos+1)-1, 2);
|
||||
payloadpos+=2;
|
||||
res=htons(res);
|
||||
}
|
||||
//! Convenience form that returns the next 16 bit integer
|
||||
uint16_t getUInt16()
|
||||
{ uint16_t ret; xfrUInt16(ret); return ret; }
|
||||
|
||||
|
||||
//! Gets the next 32 bit unsigned integer from the message
|
||||
void xfrUInt32(uint32_t& res)
|
||||
{
|
||||
memcpy(&res, &payload.at(payloadpos+3)-3, 4);
|
||||
payloadpos+=4;
|
||||
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)
|
||||
{
|
||||
if(!pos) pos = &payloadpos;
|
||||
@ -62,6 +74,7 @@ public:
|
||||
(*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 res;
|
||||
|
@ -1,7 +1,12 @@
|
||||
#include "record-types.hh"
|
||||
#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 */
|
||||
struct StringBuilder
|
||||
{
|
||||
@ -24,7 +29,6 @@ struct StringBuilder
|
||||
std::string& d_string;
|
||||
};
|
||||
|
||||
|
||||
AGen::AGen(DNSMessageReader& x)
|
||||
{
|
||||
x.xfrUInt32(d_ip);
|
||||
|
@ -6,7 +6,10 @@
|
||||
|
||||
class DNSMessageReader;
|
||||
|
||||
/*
|
||||
/*!
|
||||
@file
|
||||
@brief Defines all Resource Record Generators
|
||||
|
||||
Generators know about a record type's contents.
|
||||
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.
|
||||
@ -30,7 +33,7 @@ struct AGen : RRGen
|
||||
|
||||
uint32_t d_ip; // the actual IP
|
||||
};
|
||||
|
||||
//! Generates an AAAA (IPv6 address) record
|
||||
struct AAAAGen : RRGen
|
||||
{
|
||||
AAAAGen(DNSMessageReader& dmr);
|
||||
@ -50,6 +53,7 @@ struct AAAAGen : RRGen
|
||||
unsigned char d_ip[16];
|
||||
};
|
||||
|
||||
//! Generates a SOA Resource Record
|
||||
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) :
|
||||
@ -71,6 +75,7 @@ struct SOAGen : RRGen
|
||||
uint32_t d_serial, d_minimum, d_refresh, d_retry, d_expire;
|
||||
};
|
||||
|
||||
//! Generates a CNAME Resource Record
|
||||
struct CNAMEGen : RRGen
|
||||
{
|
||||
CNAMEGen(const DNSName& name) : d_name(name) {}
|
||||
@ -86,6 +91,7 @@ struct CNAMEGen : RRGen
|
||||
DNSName d_name;
|
||||
};
|
||||
|
||||
//! Generates a PTR Resource Record
|
||||
struct PTRGen : RRGen
|
||||
{
|
||||
PTRGen(const DNSName& name) : d_name(name) {}
|
||||
@ -100,6 +106,7 @@ struct PTRGen : RRGen
|
||||
DNSName d_name;
|
||||
};
|
||||
|
||||
//! Generates an NS Resource Record
|
||||
struct NSGen : RRGen
|
||||
{
|
||||
NSGen(const DNSName& name) : d_name(name) {}
|
||||
@ -114,7 +121,7 @@ struct NSGen : RRGen
|
||||
DNSName d_name;
|
||||
};
|
||||
|
||||
|
||||
//! Generates an MX Resource Record
|
||||
struct MXGen : RRGen
|
||||
{
|
||||
MXGen(uint16_t prio, const DNSName& name) : d_prio(prio), d_name(name) {}
|
||||
@ -131,6 +138,7 @@ struct MXGen : RRGen
|
||||
DNSName d_name;
|
||||
};
|
||||
|
||||
//! Generates an TXT Resource Record
|
||||
struct TXTGen : RRGen
|
||||
{
|
||||
TXTGen(const std::string& txt) : d_txt(txt) {}
|
||||
@ -144,7 +152,7 @@ struct TXTGen : RRGen
|
||||
std::string d_txt;
|
||||
};
|
||||
|
||||
/* This implements 'unknown record types' */
|
||||
//! This implements 'unknown record types'
|
||||
struct UnknownGen : RRGen
|
||||
{
|
||||
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; }
|
||||
};
|
||||
|
||||
//! This implements a fun dynamic TXT record type
|
||||
struct ClockTXTGen : RRGen
|
||||
{
|
||||
ClockTXTGen(const std::string& format) : d_format(format) {}
|
||||
|
@ -3,11 +3,16 @@
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include "sclasses.hh"
|
||||
#include "dns.hh"
|
||||
#include <thread>
|
||||
#include <signal.h>
|
||||
#include "record-types.hh"
|
||||
|
||||
/*!
|
||||
@file
|
||||
@brief Tiny 'dig'-like utility to create DNS queries & print responses
|
||||
*/
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
DNSName fromString(const std::string& str)
|
||||
|
14
tdns/tdns.cc
14
tdns/tdns.cc
@ -11,7 +11,6 @@
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include "sclasses.hh"
|
||||
#include "dns.hh"
|
||||
#include <thread>
|
||||
#include <signal.h>
|
||||
#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";
|
||||
}
|
||||
|
||||
/* 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)
|
||||
as a single call. This saves packets and works around implementation bugs
|
||||
over at resolvers */
|
||||
@ -274,7 +275,7 @@ static void writeTCPMessage(int sock, DNSMessageWriter& response)
|
||||
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)
|
||||
{
|
||||
string message = SRead(sock, 2);
|
||||
@ -288,7 +289,7 @@ uint16_t tcpGetLen(int sock)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
//! This is the main tdns function
|
||||
int main(int argc, char** argv)
|
||||
try
|
||||
{
|
||||
@ -444,8 +446,6 @@ try
|
||||
}
|
||||
cout<<"Hello and welcome to tdns, the teaching authoritative nameserver"<<endl;
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
|
||||
|
||||
ComboAddress local(argv[1], 53);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user