FiveCalorieDNS - Development pages
The diagram (Dia 1.0) shown below reveals part of a rough draft of the new server.
Obviously, many of the DomAns subclasses are left unshown for the sake
of brevity.
Dia 1.0
Click for additional information: Process Diagram
The hierarchy representation, a simpleton "fixed" affair built into
the query manager of the original (Four Calorie) version, will now be rolled
into a collection of objects.
Class List:
TFiveCalorieDNS
- Top level class used to instantiate all server objects.
THttpThreads
- Collection object for http server threads used for DNS monitoring
function
TThreadedQueryManager
- Maintains list of controlled domains. Finds match between requested
domain (query)
and active domain object, and allows resolution to continue
on a thread.
TDomains
- Collection object for DNS "Domains"
TDomain
- Domain object that contains TDomAns derived classes
TDomAnsTXT, TDomAnsNS, TDomAnsSOA, TDomAnsAddrRec, TDomAnsPTR, TDomAnsMX,
TDomAnsHINFO, etc
- Subclasses for TDomAns superclass.
TLog
- Retrieves statistical data for admin's browser display
TSynchronizedConfiguration
- This associated class is used to roll domain hierarchy data into and out
of
storage, and optionally, to maintain synchronization with other servers.
The diagram (Dia 2.0, below) shows the "hierarchy loop" for the domain
collection(s)
Dia 2.0
Other RR (resource records)
The original (Four Calorie) version of the DNS server could handle only
A, NS, SOA, MX, and PTR RR types, and could recognize A6/AAAA RR types well
enough to allow for graceful fallback to IPv4. However; there are other
RR types and TXT RR subtypes that are interesting and useful. Some of
these additional types will be included in the new server:
Nice to have:
Obsoleted:
There are many RR types that are security related:
- TKEY, TSIG, TA, KX, DS, IPSECKEY, RRSIG, etc
Some RR types are communication protocol specific:
- X25, ISDN, ATMA, etc
Other pertinent information:
Response codes are not uniformly utilized by internet DNS servers.
While there is an explicit code for a non-existent domain (3), many
DNS servers return ServFail (2) instead. Similarly, many servers return
the ServFail code in place of the "Not implemented" code (4).
Response Codes:
Domain Classes:
The age of the internet means that older domain classes and RR types
have been left scattered around even when better ones have been created. This "record bloat" means that
many RR types are not much used or not used at all, but are included for backward
compatibility. In the following chart, only class 1 (IN) is of much
importance, and is the only one that will be incorporated within the new
server, and the reason that the domain class is not subclassed:
Why write another DNS server?
One reason is purely personal. This author regularly sets up a large variety of
operating systems, and in the course of this work, very often has a need
for a
compact, reliable, and easy-to-configure DNS server. Additionally, a
requirement that this author holds himself bound to is the stipulation that
each server intallation must be jailed, chrooted, or otherwise isolated.
While most DNS servers can be isolated in one of the aforementioned ways,
and some even have installation scripts that "do it for you", at the end of
the day it is far easier (and gives better piece of mind) to be able to drop
a single application file into a chroot directory, along with perhaps a
C/C++ library file or two, and be done with it.
A secondary reason also has to do with security issues. Many DNS
servers have, over the years been "enhanced" with tons of additional
features. Security is inversely proportional to the number of links in
the chain. No matter that the chainsmiths are excellent, professional,
and above reproach (may even infallible), the corallary still holds sway
in the real world. Any feature that I don't need, but nonetheless resides
within the executable, is just an un-necessary risk and I don't want
to be exposed to it.
- RL Scheckelhoff
sigs: dia 1: 024744e8de0628a086fd056af85411f7
sigs: dia 2: 259af57bdf53684b923bef264988dc99
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
* File: t-domains.cpp
*
* Purpose: some basic domain building blocks for fivecdns-1.0.0
* including perpetually indexed list for domain searches
* License: (BSD-like license)
* Copyright (c) 2004, 2005, 2006, 2007, 2008 rl scheckelhoff:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY WARRANTIES
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(s) BE LIABLE FOR ANY DIRECT, INDIRECT,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "t-domains.hpp"
// Constants ...
const int DOMAIN_NAME_MIN_LENGTH = 3;
const int DOMAIN_NAME_MAX_LENGTH = 64;
//
// Construct
//
TDomains::TDomains()
{
// tbe
}
//
// Destruct
//
TDomains::~TDomains()
{
// tbe
}
//
// Add a domain to domains
//
TDomain* TDomains::Add(TDomain* objdm_ParentDomain, char* pstrDomainText)
{
try
{
TFcsError* obj_FcsErr = new TFcsError();
TDomain* objdm_NewDomain = NULL;
if (objdm_ParentDomain != NULL)
{
if (pstrDomainText != NULL)
{
if ((strlen(pstrDomainText) >= DOMAIN_NAME_MIN_LENGTH) &&
(strlen(pstrDomainText) < DOMAIN_NAME_MAX_LENGTH))
{
if (objdm_ParentDomain->objdm_Stem == NULL)
{
// No stem yet, so make it
objdm_ParentDomain->objdm_Stem = new TDomain(pstrDomainText);
if (objdm_ParentDomain->objdm_Stem != NULL)
objdm_NewDomain = objdm_ParentDomain->objdm_Stem;
else
throw(obj_FcsErr->ErrInfo(ERR_CREATE_DOMAIN, GetMsg(ERR_CREATE_DOMAIN), "TDomains::Add", true));
}
else
{
// Stem already exists, so insert new leaf
objdm_NewDomain = new TDomain(pstrDomainText);
if (objdm_NewDomain != NULL)
{
objdm_NewDomain->objdm_Parent = objdm_ParentDomain;
objdm_NewDomain = Insert(objdm_NewDomain);
}
else
throw(obj_FcsErr->ErrInfo(ERR_CREATE_DOMAIN,
GetMsg(ERR_CREATE_DOMAIN), "TDomains::Add", true)); }
}
else
throw(obj_FcsErr->ErrInfo(ERR_DOMAIN_NAME_LENGTH,
GetMsg(ERR_DOMAIN_NAME_LENGTH), "TDomains::Add", true));
}
else
throw(obj_FcsErr->ErrInfo(ERR_DOMAIN_TEXT_NULL,
GetMsg(ERR_DOMAIN_TEXT_NULL), "TDomains::Add", true));
}
else
throw(obj_FcsErr->ErrInfo(ERR_PARENT_DOMAIN_NULL,
GetMsg(ERR_PARENT_DOMAIN_NULL), "TDomains::Add", true));
delete obj_FcsErr;
return (objdm_NewDomain);
}
catch (TFcsError* obj_FcsErr)
{
if (obj_FcsErr->blnRethrow)
{
obj_FcsErr->blnRethrow = false;
throw (obj_FcsErr);
}
else
delete (obj_FcsErr);
}
}
//
// Insert a new Domain leaf
//
//
TDomain* TDomains::Insert(TDomain* objdm_New)
{
try
{
TFcsError* obj_FcsErr = new TFcsError();
TLeafInfo* obj_LeafInfo;
TDomain* objdm_Ins = objdm_New;
if (objdm_Ins != NULL)
{
if (this->objdm_Stem != NULL)
{
obj_LeafInfo = IndexKeySearch(objdm_Ins);
if (obj_LeafInfo->NoError)
{
// KeySearch was able to find appropriate insert points
objdm_Ins->objdm_HighLeaf = obj_LeafInfo->objdm_HighLeaf;
objdm_Ins->objdm_LowLeaf = obj_LeafInfo->objdm_LowLeaf;
}
else
{
objdm_Ins = NULL;
throw(obj_FcsErr->ErrInfo(ERR_INSERT_DOMAIN, GetMsg(ERR_INSERT_DOMAIN), "TDomains::Insert", true));
}
}
else
{
// Tried to insert, but no stem yet, so add as stem
this->objdm_Stem = objdm_Ins;
}
}
else
throw(obj_FcsErr->ErrInfo(ERR_DOMAIN_NULL, GetMsg(ERR_DOMAIN_NULL), "TDomains::Insert", true));
delete obj_FcsErr;
return objdm_Ins;
}
catch (TFcsError* obj_FcsErr)
{
if (obj_FcsErr->blnRethrow)
{
throw (obj_FcsErr);
}
else
delete (obj_FcsErr);
}
}