<HEAD><TITLE>MaraDNS coding style</TITLE>

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">

</HEAD><BODY>

<!-- Copyright 2007 Sam Trenholme

    TERMS

    Redistribution and use, with or without modification, are permitted 
    provided that the following condition is met:

    1. Redistributions must retain the above copyright notice, this 
       list of conditions and the following disclaimer.

    This documentation is provided 'as is' with no guarantees of 
    correctness or fitness for purpose.

 -->

<H1>MaraDNS' coding style</H1>

MaraDNS is a divergent body of code that has been developed, in some 
form or other, for over seven years.  While some changes have been made 
to that code during this time period, notably the tab and bracing style, 
some other things about the code have stayed the same.  These coding 
style guidelines have always been in mind as I was writing MaraDNS code.  
Now that MaraDNS is becoming popular enough that other people are 
starting to contribute to it, I am documenting these guidelines so that 
people can make patches that I will accept.

<p>

So, without further ado:

<h2>All indexed writes must be protected against overflows</h2>

In other words, all code that writes to arrays must be checked, before a 
write is made, to verify that the write in question is within the bounds 
of the array.  For example, this code violates MaraDNS coding styles:

<pre>
	c = &some_array;
	while(*c != 0) {
		if(*c > 'A' && *c < 'Z') 
			*c += 32;	
		c++;
	}
</pre>

In order for this kind of code to be accepted in to MaraDNS code, it 
must be revised to look like this:

<pre>
	c = &some_array;
	limit = size_of_array;
	while(*c != 0 && limit > 0) {
		if(*c > 'A' && *c < 'Z') 
			*c += 32;	
		c++;
		limit--;
	}
</pre>

<h2>All arrays must be at least one byte bigger than they should be</h2>

All arrays must be at least one byte bigger than they should be, and 
should ideally be about three bytes bigger than they should be.  In 
other words, let us suppose we have a character array that is MAX_BYTES 
long, where the bounds checking makes sure we don't write past 
MAX_BYTES.  Then we declare the array in this form:

<pre>
	char s[MAX_BYTES + 3];
</pre>

The reason for this 3-byte cushion is to prevent off-by-one errors.  An 
off-by-one error can be very dangerous.  This kind of error is why 
OpenBSD had a remote code execution exploit with its FTP daemon.  In 
MaraDNS' code, there was once a potential buffer overflow that was only 
stopped because I always have these cushions at the end of arrays.

<h2>No old MaraDNS configuration file should be broken</h2>

Unless there is a compelling reason to do so, no changes that break or 
change how an old <tt>mararc</tt> file or zone file is parsed should be 
done.  For example, there is a <tt>mararc</tt> variable entitled
<tt>default_rrany_set</tt> that does nothing in MaraDNS 1.2; we still 
support this variable (and have it do nothing) since people using 
MaraDNS since 1.0 might have this variable set.
<p>

As another example, when I changed the zone file format in MaraDNS 1.3, 
I went to a good deal of effort to make sure over 99% of MaraDNS 1.2 
zone files work completely unchanged in MaraDNS 1.3, and that a MaraDNS 
user can set a single mararc variable, <tt>csv2_tilde_handling</tt> in 
order to make MaraDNS 1.3 100% compatible with MaraDNS 1.2 zone files.
<p>

Indeed, MaraDNS 1.3 still supports MaraDNS 1.0 zone files, even though 
I am encouraging people to upgrade to the newer zone file format, and 
even though I have a Perl script that converts a MaraDNS 1.0 zone file 
in to a MaraDNS 1.2 zone file.
<p>

I have sometimes sometimes made old configuration files not compatible 
with newer versions of MaraDNS.  These changes are only done when:

<ul>
<li>There is a compelling reason to make the change in question
<li>The change in question impacts the minimum number of MaraDNS users
<li>The change in question is fully documented in MaraDNS' upgrade 
document.
</ul>

For example, MaraDNS 1.0 had a bug where it would silently ignore a 
misspelled <tt>mararc</tt> parameter.  In MaraDNS 1.2, I changed this 
behavior to one where MaraDNS will exit with a fatal error should there 
be a misspelled <tt>mararc</tt> variable.  I made this change to make 
life easier for system administrators who are wondering why a change 
isn't working in MaraDNS because they made a typo in their 
<tt>mararc</tt>.  This change, of course, is fully documented in the 
MaraDNS update document.
<p>

The reason for this is because MaraDNS users have better things to do in 
their life than to follow every single change made to MaraDNS; it's 
difficult enough for people to adjust to MaraDNS.  There is no good 
reason why we should force users to adjust to each new version just 
because we have some silly idea about what makes MaraDNS' configuration 
files neater.  This is a problem Linux and X11 developers have; I have 
had to change my custom keyboard mapping file that allows me to type 
Spanish letters and accents on a US keyboard no less than twice in the 
last few years.
<p>

There's also the issue, with French users of MaraDNS, of the French 
documentation not being updated since the 1.0 days of MaraDNS.

<h2>Brace and tab style</h2>

MaraDNS' tabbing and brace style has changed over the years.  The 
current style is to not have tabs in the code <i>at all</i>; a script 
converts all tabs in to spaces every time MaraDNS is updated.  When 
contributing new code to MaraDNS, keep this in mind:

<ul>
<li>When making a change to already existing code, try to maintain the 
bracing and spacing style of that code.
<li>For new code, there is a somewhat informal bracing style.
</ul>

Here is the bracing and tab style for new code in MaraDNS:

<pre>
int main() {
	int a;
	for(a = 0; a < 100; a++ ) {
		printf("a is %c\n",a);
	}
}
</pre>

<h2>Licensing and copyright issues</h2>

Contributions made to MaraDNS can not be accepted unless you are willing 
to license your contributions under the conditions of MaraDNS' license, 
which is a BSD license as follows:

<blockquote>
Copyright (c) 2002-2007 Sam Trenholme
<p>
TERMS
<p>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
<ol>
<li> Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
<li> 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.
</ol>
This software is provided 'as is' with no guarantees of correctness or
fitness for purpose.
</blockquote>

<h2>Contributed code must not break anything in MaraDNS</h2>

Any contributed code, before it is accepted, must not break anything in
MaraDNS.  This means the following:
<ul>

<li>The patched code must compile with no warnings nor errors when 
    compiling MaraDNS with -Wall set (the default when compiling MaraDNS).

<li>The patched code must pass all tests in the <tt>sqa/regressions</tt>
    directory.  To perform this test, first compile the patched MaraDNS.
    Next, enter the <tt>sqa/regressions</tt> directory.  Next, become root.
    Finally <tt>sh ./do.tests</tt>  

</ul>

<h2>Finally, thank you for your interest in MaraDNS</h2>

Finally, I would like to thank you for your interest in MaraDNS, and 
really appreciate the time you take to make patches for it.  I hope 
these coding style guidelines are not too bothersome; they make MaraDNS' 
code a more secure, reliable DNS server.

</BODY>
