Libreswan's Online Documentation
View the Project on GitHub libreswan/libreswan.github.io
SupportPluto previously had its own stylistic conventions but they were abandoned and starting from Libreswan 3.4 only Linux Kernel coding style is accepted.
Please read the Coding Style document thoroughly.
Your editor likely has a way to configure this. In EMACS it’s called linux style.
Idiom’s are not requirements.
you can use checkpatch.pl utility from kernel to check your patches before committing.
| git diff | checkpatch.pl –no-tree –no-signoff - |
void fun(char *s)
{
if (s == NULL) {
return "";
}
switch (*s) {
default:
s++;
return s;
case '\0':
return s;
}
}
(setq-default show-trailing-whitespace t)try to keep lines shorter than 80 columns
ikev2: implement that missing protocol
See RFC magic description.
close #555 maybe a bug
don’t use case fall-through
the operand of return need not be parenthesised
be careful with types. For example, use size_t and ssize_t.
Use const wherever possible.
really try to avoid casts
we assume and use <stdbool.h>
we like enums (they help the compiler check parameters)
streq(a,b) is clearer than strcmp(a,b) == 0. memeq is clearer than memcmp. zero is clearer than memset (but zero(&array) not zero(array)!).
to initialise a structure use {0}
use passert() and pexpect(), not assert.
side-effects of expressions are to be avoided. BAD: if (i++ == 9) OK: i++;
variables are to have as small a scope as is possible (definitions can go any where; not just at the start of the function)
for (unsigned i = 0; i < ...; i++)User “static” to limit a variable or function scope to a file.
some common names:
c is a connectionmd is a message digestst is an SA (state), either IKE or Childe is err_td is diag_topen arrays are ok
but check ITEMS_FOR_EACH() et.al.
“magic numbers” are suspect. Most integers in code stand for something. They should be given a name (using enum or #define), and that name used consistently.
It is especially bad if the same number appears in two places in a way that requires both to be changed together (eg. an array bound and a loop bound). Often sizeof or elemsof() can help.
Conditional compilation is to be avoided. It makes testing hard.
When conditionally compiling large chunks of text, it is good to put comments on #else and #endif to show what they match with. I use ! to indicate the sense of the test:
#ifdef CRUD #else /* !CRUD / #endif / !CRUD */
#ifndef CRUD #else /* CRUD / #endif / CRUD */
Never put two statements on one line. Especially empty statements. REALLY BAD: if (cat);
Exception: some macro definitions. Exception; jam_string(buf, sep); sep = “,”
don’t micro-optimise with inline functions in headers
ditto macros
Just put them in .[hc]:
macros are used as a poor-developer alternative to templates et.al.
you can use STD_ARGS in macros
you can use ({}) in macros
.c files include in the following order:
#include <system-header.h>#include "header.h"Headers from include/ are also typically included before headers from the local file.
headers have a full(C) a the top
headers are wrapped in
#ifndef HEADER_H
#define HEADER_H
#endif
so that duplicate includes do-no-harm
library headers explicitly include their dependencies
(pluto, with defs.h is a different story)
A common idiom is for the .c file to include the .h file at the top (which helps to ensure this).
all functions and variables that are exported from a .c file should be declared in that file’s corresponding header file.
Make sure that the .c file includes the header so that the declaration and the definition will be checked for consistency by the compiler.
There is no excuse for the “extern” keyword in a .c file.
There is almost no excuse for the declaration of an object within a .h file to NOT have the “extern” keyword. We are a lax about this for function declarations (because a definition is clearly marked by the presence of the function body).
Technical detail: C has declarations of variables and functions. Some of these are definitions. Some are even “tentative definitions”. We don’t want definitions or tentative definitions within .h files. We don’t want declarations that are not definitions within .c files. “extern” usually signifies a variable declaration that isn’t a definition.
we use custom wrappers around malloc() and free(); see lswalloc.h
it guarantees zero on allocate, and scrambled on free
it includes macros to overallocate buffers and allocate arrays
if you mix it with malloc() et.al., pluto will core dump
it detects unreleased memory
in addition, many structures are reference counted; see refcnt.h
calls to NSS often require the use of the NSS allocator
we do not use alloca() nor dynamic arrays
Most objects include a logger (state->logger, md->logger, …) that contains context (prefix) for the message; removing the need to include context in the message.
Log messages are not complete sentences, i.e., they don’t start with a capital or end in a full stop, use ; to break long messages.
There are two ways to emit log messages:
oh, and two more:
when manipulating bytes and string we use hunk like objects; they contain a .ptr (or buffer) and a .len field
for raw bytes, such as received over the wire, we use the predefined chunk_t type
Functions and macros to manipulate byte buffers can be found in chunk.h and hunk.h.
To detect an empty buffer test .len==0 and not .ptr=NULL.
struct {
unsigned len;
uint8_t *ptr;
}
for strings, such as when processing config files, we strongly prefer the predefined shunk_t type
Unlike C’s traditional const char * it has a bound.
Functions and macros to manipulate string buffers can be found in shunk.h and hunk.h.
To detect an empty buffer test .len==0 and not .ptr=NULL.
struct {
unsigned len;
const void *ptr;
}
finally other structures can contain .ptr and .len making them hunk like
NSS has a similar, but annoyingly different, SECItem
(chunk_t predates Libreswan using NSS, hence the difference)
Libreswan has two types of name tables for converting between names an numeric values: enum_names and sparse_names. The former is good for enums where values are consecutive; the latter where values are discontinuous.