<HEAD><TITLE>MaraDNS coding style</TITLE> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8"> </HEAD><BODY> <!-- Copyright 2007,2009 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.4 100% compatible with MaraDNS 1.2 zone files. <p> 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. <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. <p> 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. <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-2009 Sam Trenholme and others <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>