`sys/queue.h` has it's pointers to the next element rather than the next list_node, while `ccan` and `linux` have pointers to the next list_node, which then are adjusted if needed to obtain the containing element.
In practice, this means that `sys/queue.h` is entirely macros, while linux & ccan's lists can use normal functions for most operations (with primarily obtaining the element pointer being handled by macros). Whether or not this is useful is somewhat dependent on compile time costs for macros vs code, and how small the list operations are in code size (ie: are they always inlined, or is it useful to be able to have a single instance of them). With the linux model, this can be determined at any time (by the compiler, or by the linked list library by changing it a bit), with the bsd model it is somewhat more difficult to make work (one could possibly do this by passing in the offset of the list_node structure to functions).