MaraDNS' coding style
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.
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 after when and if
MaraDNS 2.0 comes out.
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-2009 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.