==== MaraDNS coding style ====

=== MaraDNS' coding style ===

MaraDNS is a divergent body of code that has been developed, in some 
form or other, for nearly a decade. 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. 

Please note that the only patches I will accept for MaraDNS 1.4 and 
MaraDNS 2.0 are patches that fix bugs and do not add any features to 
the code. MaraDNS is open-source and people interesting in adding 
features to the code are free to make their own MaraDNS fork. Please do 
not name any such fork "MaraDNS". 

So, without further ado: 

== All indexed writes must be protected against overflows ==

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:

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

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

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

== All arrays must be at least one byte bigger than they should be ==

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:

	char s[MAX_BYTES + 3];

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. 

== No old MaraDNS configuration file should be broken ==

Unless there is a compelling reason to do so, no changes that break or 
change how an old mararc file or zone file is parsed should be done. 
For example, there is a mararc variable entitled default_rrany_set 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. 

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, csv2_tilde_handling in order to 
make MaraDNS 1.4 100% compatible with MaraDNS 1.2 zone files. 

Indeed, MaraDNS 1.4 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. 

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

* There is a compelling reason to make the change in question

* The change in question impacts the minimum number of MaraDNS users

* The change in question is fully documented in MaraDNS' upgrade 
  document.

For example, MaraDNS 1.0 had a bug where it would silently ignore a 
misspelled mararc parameter. In MaraDNS 1.2, I changed this behavior to 
one where MaraDNS will exit with a fatal error should there be a 
misspelled mararc 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 mararc. This change, of 
course, is fully documented in the MaraDNS update document. 

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. 

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

Note that MaraDNS 2.0 will break many configurations, since the same IP 
will be unable to be both a recursive and authoritative DNS server. 
This is why I will continue to support MaraDNS 1.4 for the foreseeable 
future even though MaraDNS 2.0 has been released. 

== Brace and tab style ==

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

* When making a change to already existing code, try to maintain the 
  bracing and spacing style of that code.

* For new code, there is a somewhat informal bracing style.

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

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

== Licensing and copyright issues ==

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: 

Copyright (c) 2002-2010 Sam Trenholme and others 

TERMS 

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are 
met: 

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

* 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 'as is' with no guarantees of correctness or 
fitness for purpose. 

== Contributed code must not break anything in MaraDNS ==

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

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

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

== Finally, thank you for your interest in MaraDNS ==

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.  

