Contributing

If you want to start contributing to bpfilter, the best way to get to know the codebase would be to start with one of the @todo available in the code. Most of those tasks are small, self-contained, work trivial enough that they do not deserve their GitHub issue.

Once you know your way around the structure of the project, feel free to continue with the @todo, or jump on a bigger issue in the GitHub issues tracker.

You are welcome to reach out to qde@naccy.de if you need help, or have any question!

To do

  • Enforce clang-format and clang-tidy on all source files.

  • Remove the RPM x86_64 macro workaround from the Fedora bpfilter.spec.

  • Gate the documentation generate in Fedora’s bpfilter.spec with a bcond.

  • Add support for CMake 4.0 and ninja.

  • Handle extra characters in the lexer (currently, any non-matched token will be printed to stdout).

  • Add support for missing matcher operators (e.g. meta.l4_proto not).

  • Add a Fedora 43 build in the CI.

From the code

page todo

Global _bf_ipt_set_counters_handler  (const struct xt_counters_info *counters, size_t len)

Actually update the counters.

Global _bf_matcher_generate_meta_iface  (struct bf_program *program, const struct bf_matcher *matcher)

Add support for input and output interface filtering based on the program’s hook.

Global _bf_save  (const char *path)

Front packing should be name-based to avoid relying on the enumeration order.

Global bf_cgen::program

The codegen should not store the program: it creates a bf_program to generate the bytecode, attach it, and only keep the program’s FD (and maps). No need to keep the bytecode, nor (de)serializing it.

Global bf_cgen_set  (struct bf_cgen *cgen, const struct bf_ns *ns, struct bf_hookopts **hookopts)

bf_cgen should not store a bf_program object pointer, it should create a new program during generation, use it, then discard it. The program is not needed once loaded, it should be considered as a temporary artifact.

Global bf_chain_add_rule  (struct bf_chain *chain, struct bf_rule *rule)

Rules without any matcher should be rejected.

Struct bf_front_ops

Front should not implement a callback if it’s not needed. E.g. BF_FRONT_CLI defines empty pack and unpack callbacks.

Struct bf_hookopts

Create dedicated function to set the various options, otherwise one could set an option but not update used_opts.

Global bf_hookopts_new_from_pack  (struct bf_hookopts **hookopts, bf_rpack_node_t node)

Validate the hook options once restored.

Global bf_link_attach  (struct bf_link *link, enum bf_hook hook, struct bf_hookopts **hookopts, int prog_fd)

Automatically use the most appropriate XDP mode based on the driver’s capabilities.

Validate hookopts before attaching the link.

Struct bf_matcher

bf_matcher’s payload should be a union of all the possible payload types.

Global bf_ns_init  (struct bf_ns *ns, pid_t pid)

What if /proc is not readable?

Global bf_options::transient

Validate the daemon’s behaviour when switch to and from --transient.

Global bf_program::link

A bf_program should not have any link until the program is attached.

Global bf_program_generate  (struct bf_program *program)

Allow chains to have no counters at all.

Global bf_program_new_from_pack  (struct bf_program **program, const struct bf_chain *chain, int dir_fd, bf_rpack_node_t node)

bf_program should be recreated from the current system state by using BF_OBJ_INFO_BF_FD, and not serialized.

Global bf_request::data  []

Return a user-readable error message if the request fails.

Global bf_swich_generate  (struct bf_swich *swich)

If no default case is defined, the switch should jump after the last case.

Global closep  (int *fd)

Ensure file descriptors are always initialized to -1, and closed using closep.

File list.h

Create bf_list_push function.

bf_list_add_XXX functions should probably steal the pointer of the data they receive, to be more consistent with other functions, and avoid TAKE_PTR() after bf_list_add_tail().

File matcher.h

The matcher type/op/payload size combination should be validated.

Use a union value instead of an opaque value for matcher payload. All supported payloads have a fixed, well-known size. We should leverage the type system to avoid writing/reading raw bytes.

File pack.h

bf_wpack_kv_TYPE functions should only write into objects.

bf_wpack_TYPE functions should only write into arrays.

Create dedicated functions to pack and unpack a size_t and ssize_t.

Functions that write to the pack object should be more verbose: even if they don’t return an error code, they should log a warning when a packing operation fails.