<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="KEYWORDS" content="Developer guide" /> <meta name="robots" content="index,follow" /> <link rel="shortcut icon" href="favicon.ico" /> <title>Developer guide - DNSdoctor</title> <style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "/skins/monobook/main.css"; /*]]>*/</style> <link rel="stylesheet" type="text/css" media="print" href="commonPrint.css" /> <!--[if lt IE 5.5000]><style type="text/css">@import "/skins/monobook/IE50Fixes.css";</style><![endif]--> <!--[if IE 5.5000]><style type="text/css">@import "/skins/monobook/IE55Fixes.css";</style><![endif]--> <!--[if gte IE 6]><style type="text/css">@import "/skins/monobook/IE60Fixes.css";</style><![endif]--> <!--[if IE]><script type="text/javascript" src="/skins/common/IEFixes.js"></script> <meta http-equiv="imagetoolbar" content="no" /><![endif]--> <script type="text/javascript" src="index.html%3Ftitle=-&action=raw&gen=js"></script> <script type="text/javascript" src="wikibits.js"></script> <style type="text/css">/*<![CDATA[*/ @import "/?title=MediaWiki:Monobook.css&action=raw&ctype=text/css&smaxage=18000"; @import "/?title=-&action=raw&gen=css&maxage=18000"; /*]]>*/</style> </head> <body class="ns-0"> <div id="globalWrapper"> <div id="column-content"> <div id="content"> <a name="top" id="top"></a> <h1 class="firstHeading">Developer guide</h1> <div id="bodyContent"> <h3 id="siteSub">From DNSdoctor</h3> <div id="contentSub"></div> <!-- start content --> <table id='toc' class='toc'><tr><td><div id='toctitle'><h2>Contents</h2></div> <ul> <li class='toclevel-1'><a href="Developer_guide.1.html#Internal_design"><span class="tocnumber">1</span> <span class="toctext">Internal design</span></a> <ul> <li class='toclevel-2'><a href="Developer_guide.1.html#Localisation"><span class="tocnumber">1.1</span> <span class="toctext">Localisation</span></a></li> </ul> </li> <li class='toclevel-1'><a href="Developer_guide.1.html#Extending"><span class="tocnumber">2</span> <span class="toctext">Extending</span></a> <ul> <li class='toclevel-2'><a href="Developer_guide.1.html#Localization"><span class="tocnumber">2.1</span> <span class="toctext">Localization</span></a></li> <li class='toclevel-2'><a href="Developer_guide.1.html#Implementing_new_tests"><span class="tocnumber">2.2</span> <span class="toctext">Implementing new tests</span></a></li> <li class='toclevel-2'><a href="Developer_guide.1.html#Adding_input_interface"><span class="tocnumber">2.3</span> <span class="toctext">Adding input interface</span></a></li> <li class='toclevel-2'><a href="Developer_guide.1.html#Adding_publisher"><span class="tocnumber">2.4</span> <span class="toctext">Adding publisher</span></a></li> </ul> </li> </ul> </td></tr></table> <p><script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script> </p> <div class="editsection" style="float:right;margin-left:5px;">[<a href="http://www.dnsdoctor.org/?title=Developer_guide&action=edit&section=1" title="Developer guide">edit</a>]</div><a name="Internal_design"></a><h1> Internal design </h1> <div class="editsection" style="float:right;margin-left:5px;">[<a href="http://www.dnsdoctor.org/?title=Developer_guide&action=edit&section=2" title="Developer guide">edit</a>]</div><a name="Localisation"></a><h2> Localisation </h2> <pre> <check name="soa_ns_cname"> <name>SOA master is not an alias</name> <success>The SOA master is not an alias</success> <failure>SOA master is not allowed to point to a CNAME alias</failure> <explanation sameas="shortcut:ns_cname"/> <details><para>The master (<var name="master"/>) is a CNAME alias to <var name="alias"/>.</para></details> </check> </pre> <pre> <shortcut> <explanation name="email_sntx"> <src type="ref" from="rfc" fid="rfc1034#p9"> <title>IETF RFC1034 (p.9), RFC1912 (p.3)</title> <para>Email addresses are converted by using the following rule: local-part@mail-domain ==> local-part.mail-domain if local-part contains a dot in should be backslashed (for 'bind').</para> </src> </explanation> </shortcut> <check name="soa_contact_sntx_at"> <name>misused '@' characters in SOA contact name</name> <success>No misuse of '@' character in SOA contact name</success> <failure>The contact name contains the character '@'</failure> <explanation sameas="shortcut:email_sntx"/> <details/> </check> </pre> <p><br /> This is the DTD used to describe the message catalog: </p> <pre><!ELEMENT msgcat ((shortcut|check|test)*|(section|tag)*)> <!ELEMENT shortcut (explanation|details)*> <!ELEMENT check (name,success,failure,explanation,details)> <!ELEMENT test (name)> <!ELEMENT name (#PCDATA|var|const)*> <!ELEMENT failure (#PCDATA|var|const)*> <!ELEMENT success (#PCDATA|var|const)*> <!ELEMENT explanation (src*)> <!ELEMENT details (para*)> <!ELEMENT src (title,para+)> <!ELEMENT title (#PCDATA|var|const)*> <!ELEMENT para (#PCDATA|var|const|uri)*> <!ELEMENT var EMPTY> <!ELEMENT const EMPTY> <!ELEMENT uri (#PCDATA)> <!ELEMENT tag (#PCDATA)> <!ELEMENT section (tag*)> <!ATTLIST msgcat lang CDATA #REQUIRED> <!ATTLIST check name CDATA #REQUIRED> <!ATTLIST test name CDATA #REQUIRED> <!ATTLIST explanation name CDATA #IMPLIED sameas CDATA #IMPLIED> <!ATTLIST details name CDATA #IMPLIED sameas CDATA #IMPLIED> <!ATTLIST src type CDATA #REQUIRED from CDATA #IMPLIED fid CDATA #IMPLIED> <!ATTLIST uri link CDATA #REQUIRED> <!ATTLIST var name CDATA #REQUIRED> <!ATTLIST var display CDATA #IMPLIED> <!ATTLIST const name CDATA #REQUIRED> <!ATTLIST const display CDATA #IMPLIED> <!ATTLIST section name CDATA #REQUIRED> <!ATTLIST tag name CDATA #REQUIRED> </pre> <div class="editsection" style="float:right;margin-left:5px;">[<a href="http://www.dnsdoctor.org/?title=Developer_guide&action=edit&section=3" title="Developer guide">edit</a>]</div><a name="Extending"></a><h1> Extending </h1> <div class="editsection" style="float:right;margin-left:5px;">[<a href="http://www.dnsdoctor.org/?title=Developer_guide&action=edit&section=4" title="Developer guide">edit</a>]</div><a name="Localization"></a><h2> Localization </h2> <p>All the localization files are located in the <tt>locale</tt> directory and the files have for suffix the corresponding langue. For example the main locale file for <tt>dnsdoctor</tt> will be <tt>dnsdoctor.en</tt> for a locale set to <b>en</b>_US.UTF-8. </p><p>The localization catalogue has been split into several files to make the addition of new input interfaces or tests easier, so the division is as follow: </p> <ul><li> DNSdoctor: dnsdoctor.* </li><li> Input interface: cli.* cgi.* inetd.* gtk.* </li><li> Tests: test/soa.* test/ns.* test/interop.* ... </li></ul> <div class="editsection" style="float:right;margin-left:5px;">[<a href="http://www.dnsdoctor.org/?title=Developer_guide&action=edit&section=5" title="Developer guide">edit</a>]</div><a name="Implementing_new_tests"></a><h2> Implementing new tests </h2> <p>Tests are stored in the directory <tt>test</tt> and are automatically loaded by dnsdoctor. </p><p>There are four types of tests, and the type of the test is defined by the module to which it belongs: </p> <dl><dt> CheckGeneric </dt><dd> The test doesn't need to know the nameserver nor the IP addresses.<br /> No parameters are used by the method: <code>chk_testname()</code> </dd><dt> CheckNameServer </dt><dd> The test need to know the nameserver. <br />One parameter is used by the method: <code>chk_testname(ns)</code> </dd><dt> CheckNetworkAddress </dt><dd> The test need to know the nameserver and the IP address. <br />Two parameters are used by the method: <code>chk_testname(ns, ip)</code> </dd><dt> CheckExtra </dt><dd> The test is not really DNS related and so doesn't need to know the nameserver nor the IP addresses. <br />No parameters are used by the method: <code>chk_testname()</code> </dd></dl> <p><br /> The method defining a test must also be part of a <tt>class</tt>, this allows creating intermediate functions that can be used by a set of related tests, and the <tt>class</tt> should inherit from <tt>Test</tt>. </p><p>There are two types of methods used by the test engine: </p> <dl><dt> chk_<i>name</i> </dt><dd> It is the check, if the return value is <tt>true</tt> the check was succesful, otherwise if the return value is <tt>false</tt> or an hash or an exception it is a failure. In the case of a hash, the key/value are used to perform a substitution in the message generated for tokent marked as variables; for the exception the message stored in it is displayed without localization as it is generally an error tied to the operating system. </dd><dt> tst_<i>name</i> </dt><dd> It is a conditional, the method should return a string that will be used in a <tt>case</tt> statement. </dd></dl> <p><br /> The corresponding message catalog should be loaded for the set of tests that we are defining, this is done by adding the <code>with_msgcat 'test/<i>catname</i>.%s'</code> in the class, generally <i>catname</i> is the same name as the class in lowercase. </p><p><br /> Below is an example implementing the check <i>soa_ns_cname</i> which check that the master used in the <tt>SOA</tt> records doesn't resolve into a <tt>CNAME</tt>, if it is the case the check fails and returns the name of the master and the name of the <tt>CNAME</tt>. </p> <pre>require 'framework' module CheckNetworkAddress class SOA < Test with_msgcat 'test/soa.%s' def chk_soa_ns_cname(ns, ip) return true unless name = is_cname?(soa(ip).mname, ip) { 'master' => soa(ip).mname, 'alias' => name } end end end </pre> <p>And this is the fragment corresponding to the localization in english: </p> <pre> <check name="soa_ns_cname"> <name>SOA master is not an alias</name> <success>The SOA master is not an alias</success> <failure>SOA master is not allowed to point to a CNAME alias</failure> <explanation sameas="shortcut:ns_cname"/> <details><para>The master (<var name="master"/>) is a CNAME alias to <var name="alias"/>.</para></details> </check> </pre> <div class="editsection" style="float:right;margin-left:5px;">[<a href="http://www.dnsdoctor.org/?title=Developer_guide&action=edit&section=6" title="Developer guide">edit</a>]</div><a name="Adding_input_interface"></a><h2> Adding input interface </h2> <p>New input interfaces should be part of the module <tt>Input</tt> and the class implementing it should be in uppercase, the file storing it in lowercase and in the directory <tt>zc/input</tt>, but the name should be the same (except for the case). </p> <dl><dt> allow_preset </dt><dd> Returns true if the interface is able to use preset values as stored in the <tt>dnsdoctor.conf</tt> configuration file. </dd><dt> initialize </dt><dd> Initialise the class. </dd><dt> restart </dt><dd> Method to call for restarting the input interface (must reinitialize internal values). </dd><dt> parse(param) </dt><dd> Fill the parameter holder (<tt>param</tt>) from the parsing of primary input information. </dd><dt> interact(param, config, testmanager, io) </dt><dd> Allow a deeper interaction with the user, the information available are the parameters (<tt>param</tt>), the configuration (<tt>config</tt>) provided by <tt>dnsdoctor.conf</tt> and the test manager (<tt>testmanager</tt>). And it is still possible to change the parameters </dd><dt> usage(errcode, io) </dt><dd> Display usage normally using the <tt>io</tt> provided and exit if <tt>errcode</tt> is not <tt>nil</tt>. </dd><dt> error(str, errcode, io) </dt><dd> Display the error provided as a string using the <tt>io</tt> provided and exit if <tt>errcode</tt> is not <tt>nil</tt>. </dd></dl> <p><br /> This is the structure of the class used by the CGI Input (for more information you can look at the various implementation in <tt>zc/input/</tt>): </p> <pre>module Input class CGI with_msgcat "cgi.%s" def allow_preset ; false ; end def initialize ; ..... ; end def restart ; ..... ; end def parse(p) ; ..... ; end def interact(p, c, tm, io=$console.stdout) ; ..... ; end def usage(errcode, io=$console.stdout) ; ..... ; end def error(str, errcode=nil, io=$console.stdout) ; ..... ; end end end </pre> <div class="editsection" style="float:right;margin-left:5px;">[<a href="http://www.dnsdoctor.org/?title=Developer_guide&action=edit&section=7" title="Developer guide">edit</a>]</div><a name="Adding_publisher"></a><h2> Adding publisher </h2> <p>New publisher should be part of the module Publisher and the class implementing it should inherit from <tt>Template</tt>, the file storing it should be in the <tt>zc/publisher</tt> directory. Unlike new tests or input interface, new publisher are not automatically loaded and should be added in the <tt>param.rb</tt> file. </p> <dl><dt> error(text) </dt><dd> Print the <tt>text</tt> in case of error. </dd><dt> intro(domain) </dt><dd> Print a summary information about the domain being tested, generally the domain name and its nameservers. </dd><dt> diag_start() </dt><dd> This method is called when dnsdoctor will start to send diagnostic messages (ie: calling <tt>diagnostic</tt>) </dd><dt> diagnostic1(domainname, i_count, i_unexp, w_count, w_unexp, f_count, f_unexp, res, severity) </dt><dd> Print a one line (generally two lines) of information about the status of the domain <tt>domainname</tt> tested <b>i</b>nformations, <b>w</b>arnings and <b>f</b>atals being <b>count</b>ed and a flag is set if it was due to an exception (<b>unexp</b>ected), <tt>res</tt> and <tt>severity</tt> holding information about the more significant message. </dd><dt> diagnostic(severity, testname, desc, lst) </dt><dd> According to <tt>severity</tt> print a informational, warning or fatal message for the test <tt>testname</tt>, the description being given by <tt>desc</tt> and the list of host to which it appplies by <tt>lst</tt>. </dd><dt> status(domainname, i_count, w_count, f_count) </dt><dd> Display the final status for the domain <tt>domainname</tt> <b>i</b>nformations, <b>w</b>arnings and <b>f</b>atals being <b>count</b>ed </dd><dt> setup(domain_name) </dt><dd> Allow earlier initialisation. For HTML pages it is usefull for setting the page title in the head structure. </dd></dl> <p><br /> This is the structure of the class used by the Text publisher (for more information you can look at the various implementation in zc/publisher/): </p> <pre>module Publisher class Text < Template Mime = "text/plain" def error(text) ; ... ; end def intro(domain) ; ... ; end def diag_start() ; ... ; end def diag_section(title) ; ... ; end def diagnostic1(domainname, i_count, i_unexp, w_count, w_unexp, f_count, f_unexp, res, severity) ; .. ;end def diagnostic(severity, testname, desc, lst) ; ... ; end def status(domainname, i_count, w_count, f_count) ; ... ; end def setup(domain_name) ; ... ; end end end </pre> <!-- Saved in parser cache with key dnsdoctor_wiki:pcache:idhash:743-0!1!0!0!!en!2 and timestamp 20060212185255 --> <div class="printfooter"> Retrieved from "<a href="http://www.dnsdoctor.org/Developer_guide">http://www.dnsdoctor.org/Developer_guide</a>"</div> <div id="catlinks"><p class='catlinks'><a href="http://www.dnsdoctor.org/?title=Special:Categories&article=Developer_guide" title="Special:Categories">Categories</a>: <a href="http://www.dnsdoctor.org/Category:Documentation" title="Category:Documentation">Documentation</a></p></div> <!-- end content --> <div class="visualClear"></div> </div> </div> </div> <div id="column-one"> <div id="p-cactions" class="portlet"> <h5>Views</h5> <ul> <li id="ca-nstab-main" class="selected" ><a href="http://www.dnsdoctor.org/Developer_guide">Article</a></li><li id="ca-talk" class="new" ><a href="http://www.dnsdoctor.org/?title=Talk:Developer_guide&action=edit">Discussion</a></li><li id="ca-edit" ><a href="http://www.dnsdoctor.org/?title=Developer_guide&action=edit">Edit</a></li><li id="ca-history" ><a href="http://www.dnsdoctor.org/?title=Developer_guide&action=history">History</a></li> </ul> </div> <div class="portlet" id="p-personal"> <h5>Personal tools</h5> <div class="pBody"> <ul> <li id="pt-login"><a href="http://www.dnsdoctor.org/?title=Special:Userlogin&returnto=Developer_guide">Create an account or log in</a></li> </ul> </div> </div> <div class="portlet" id="p-logo"> <a style="background-image: url(/images/docteur4.png);" href="http://www.dnsdoctor.org/Main_Page" title="Main Page"></a> </div> <script type="text/javascript"> if (window.isMSIE55) fixalpha(); </script> <div class='portlet' id='p-navigation'> <h5>Navigation</h5> <div class='pBody'> <ul> <li id="n-DNSdoctor"><a href="http://www.dnsdoctor.org/DNSdoctor">DNSdoctor</a></li> <li id="n-portal"><a href="http://www.dnsdoctor.org/DNSdoctor:Community_Portal">Community portal</a></li> <li id="n-currentevents"><a href="http://www.dnsdoctor.org/Current_events">Current events</a></li> <li id="n-Screenshots"><a href="http://www.dnsdoctor.org/Screenshots">Screenshots</a></li> <li id="n-Documentation"><a href="http://www.dnsdoctor.org/Documentation">Documentation</a></li> <li id="n-Download"><a href="http://www.dnsdoctor.org/Download">Download</a></li> <li id="n-Releases"><a href="http://www.dnsdoctor.org/Releases">Releases</a></li> <li id="n-Resources"><a href="http://www.dnsdoctor.org/Resources">Resources</a></li> <li id="n-Roadmap"><a href="http://www.dnsdoctor.org/Roadmap">Roadmap</a></li> <li id="n-CVS"><a href="http://www.dnsdoctor.org/CVS">CVS</a></li> <li id="n-Bugs"><a href="http://www.dnsdoctor.org/Bugs">Bugs</a></li> <li id="n-History/Credits"><a href="http://www.dnsdoctor.org/History/Credits">History/Credits</a></li> </ul> </div> </div> <div id="p-search" class="portlet"> <h5><label for="searchInput">Search</label></h5> <div class="pBody"> <form name="searchform" action="http://www.dnsdoctor.org/Special:Search" id="searchform"> <input id="searchInput" name="search" type="text" accesskey="f" value="" /> <input type='submit' name="go" class="searchButton" id="searchGoButton" value="Go" /> <input type='submit' name="fulltext" class="searchButton" value="Search" /> </form> </div> </div> <div class="portlet" id="p-tb"> <h5>Toolbox</h5> <div class="pBody"> <ul> <li id="t-whatlinkshere"><a href="http://www.dnsdoctor.org/Special:Whatlinkshere/Developer_guide">What links here</a></li> <li id="t-recentchangeslinked"><a href="http://www.dnsdoctor.org/Special:Recentchangeslinked/Developer_guide">Related changes</a></li> <li id="t-specialpages"><a href="http://www.dnsdoctor.org/Special:Specialpages">Special pages</a></li> <li id="t-print"><a href="http://www.dnsdoctor.org/?title=Developer_guide&printable=yes">Printable version</a></li> </ul> </div> </div> </div><!-- end of the left (by default at least) column --> <div class="visualClear"></div> <div id="footer"> <div id="f-poweredbyico"><a href="http://www.mediawiki.org/"><img src="poweredby_mediawiki_88x31.png" alt="MediaWiki" /></a></div> <ul id="f-list"> <li id="f-lastmod"> This page was last modified 22:33, 7 October 2004.</li> <li id="f-viewcount">This page has been accessed 391 times.</li> <li id="f-about"><a href="http://www.dnsdoctor.org/DNSdoctor:About" title="DNSdoctor:About">About DNSdoctor</a></li> <li id="f-disclaimer"><a href="http://www.dnsdoctor.org/DNSdoctor:General_disclaimer" title="DNSdoctor:General disclaimer">Disclaimers</a></li> </ul> </div> </div> <!-- Served by www.dnsdoctor.org in 0.28 secs. --> </body> </html>