summaryrefslogtreecommitdiff
path: root/src/ipcpd
Commit message (Collapse)AuthorAgeFilesLines
* lib: Use push/pop for ssm_pk_buff opsDimitri Staessens4 days3-6/+6
| | | | | | | | | Renames the allocation for head/tail to push/pop instead of alloc/release as it's simpler and shorter. Took this approach insted of adopting the kernel's push/pull/put/trim. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd-eth: Tune raw sockets and retry queriesDimitri Staessens4 days2-62/+113
| | | | | | | | | | | | | | | | | | | Add IPCP_ETH_SNDBUF/RCVBUF cmake build options so deployments can size the AF_PACKET socket buffers without patching code. Drop the O_NONBLOCK fcntl on the raw socket in favour of per-recvfrom MSG_DONTWAIT so race-loser reader threads exit with EAGAIN without spamming the log. Track frame send failures and the SO_SNDBUF size in the eth/summary RIB; log a one-shot warning when the kernel reports AF_PACKET drops. Retry name queries up to NAME_QUERY_RETRIES times within NAME_QUERY_TIMEO; a single lost ARP-style mgmt frame no longer fails the query. Bump IRMd QUERY_TIMEOUT from 200 ms to 2200 ms so the IRMd budget exceeds the new shim retry window. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Pass MTU from IPCP to process for FRCTDimitri Staessens4 days9-13/+79
| | | | | | | | | FRCT needs to know the MTU for fragmentation. The MTU is now passed from the layer serving the flow to the process as part of flow allocation. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Rename PROG_* config to PROC_*Dimitri Staessens4 days5-25/+25
| | | | | | | | | Per-process flow / fd / fqueue limits are properties of a process, not a program; align the naming. Mechanical rename of PROG_MAX_FLOWS, PROG_RES_FDS, and PROG_MAX_FQUEUES to PROC_*. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Reject outbound packets on ethDimitri Staessens4 days1-2/+16
| | | | | | | | | | | | | AF_PACKET under `tc netem duplicate`, produces an extra PACKET_OUTGOING frame at the source that receive path didn't reject. Read with recvfrom(2) and discard frames whose sll_pkttype is PACKET_OUTGOING. Restores the dst-MAC check body (defense in depth, also bumps n_bad_id) so any frame addressed neither to us nor the broadcast MAC is dropped before flow lookup. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* include: Centralise atomic helpers in atomics.hDimitri Staessens4 days1-5/+4
| | | | | | | | Moves the atomics macros that were defined between eth and ssm_pool to their own header. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Expose ipcpd-eth flow statistics via RIBDimitri Staessens4 days2-8/+333
| | | | | | | | | | | | | Adds an IPCP_ETH_FLOW_STATS cmake option (gated on HAVE_FUSE; default off) exposing per-flow and aggregate frame counters at /<ipcp>/eth/{summary,<fd>}. Counters use RELAXED atomics; the macros expand to ((void) 0) when the option is off. Per-flow and global counters live in nested stat structs. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Validate wire frame lengthsDimitri Staessens4 days2-6/+10
| | | | | | | | Asserting frame lengths coming from the wire was a severe flaw. Fixed by gracefully dropping runt frames. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Add header checksum to ipcpd-ethDimitri Staessens2026-05-061-6/+56
| | | | | | | | | The internal flow allocator header had no checksum protection. While it is protected by the Ethernet FCS, lacking a header checksum fails netem corruption tests. It adds protection against in-memory bitflips. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix certificate DER encoding and key buffersDimitri Staessens2026-03-141-2/+2
| | | | | | | | | | | i2d_X509() allocated buf->data via OPENSSL_malloc(), but callers free it with freebuf() which uses free(). Fix by allocating with malloc() and encoding directly into the buffer. Also replaces MSGBUFSZ with CRYPT_KEY_BUFSZ (4096) for key material buffers and removes leftover debug logging. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Fix rejected flow allocation on localDimitri Staessens2026-03-141-9/+6
| | | | | | | | | When the server rejects the flow, the local didn't send the flow_alloc response back to the IRMd, causing the irmd and client to time out instead of being notified of the failed allocation immediately. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Skip vertices with empty forwarding listsDimitri Staessens2026-02-221-21/+23
| | | | | | | | | | | | | | | Fixes ECMP routing table to skip unreachable vertices with empty forwarding lists, avoiding uninitialized nhop access. Replace inner vertex list walk with bounded index loop instead of using a list_for_each to track indices (which confuses the static analyzer as it seems it can't prove the index remains valid). Remove spurious free(*dist) on ECMP success path (caller frees). Extract edge cleanup into free_edges helper in del_vertex to avoid a static analyzer false positive. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Fix unused values in unicast IPCPDimitri Staessens2026-02-222-4/+2
| | | | | | | | | | | Use the key in the store operation in the DHT, to avoid static analyzer seeing it as being set without being used in release builds. The length of the packet buffer is only used when tracking DT stats, so should be set within the IPCP_FLOW_STATS guard. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Fix lsdb being renamed to lspbDimitri Staessens2026-02-181-32/+32
| | | | | | | | A recent bulk rename of sdb -> spb (shm du buff to shm pkt buff) unintentionally renamed the lsdb. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Add struct llist for lists tracking lenDimitri Staessens2026-02-185-354/+253
| | | | | | | | | | | | | The DHT uses a struct {struct list_head, size_t len} pattern, which is also useful in the registry and other places. Having a struct llist (defined in list.h) with consistent macros for addition/deletion etc removes a lot of duplication and boilerplate and reduces the risk of inconsistent updates. The list management is now a macro-only implementation. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Update copyright to 2026Dimitri Staessens2026-02-1874-74/+74
| | | | | Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Add SLH-DSA tests and per-algorithm PQC gatingDimitri Staessens2026-02-181-1/+1
| | | | | | | | | | | | | | | | | This replaces the single HAVE_OPENSSL_PQC/DISABLE_PQC with per-algorithm CMake variables (ML-KEM, ML-DSA, SLH-DSA), gated by the OpenSSL versions: ML-KEM and ML-DSA require >= 3.4, SLH-DSA >= 3.5. SLH-DSA was already working, but now added explicit authentication tests for it with a full certificate chain (root CA, intermediate CA, server) to show full support. Rename PQC test files and cert headers to use algorithm-specific names (ml_kem, ml_dsa, slh_dsa) and move cert headers to include/test/certs/. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Fix invisible IPCP_TARGET variablesDimitri Staessens2026-02-135-12/+0
| | | | | | | | | | | | | | | | The IPCP_*_TARGET variables (e.g., set(IPCP_LOCAL_TARGET ipcpd-local)) were defined locally in each IPCP's CMakeLists.txt (e.g., CMakeLists.txt), but the configure_file() that substitutes @IPCP_LOCAL_TARGET@ into config.h.in runs in a sibling scope that is processed before ipcpd. Since CMake variables don't propagate between sibling directory scopes, all @IPCP_*_TARGET@ substituted to empty strings, resulting in IPCP_LOCAL_EXEC "". Moved the IPCP_*_TARGET definitions into the cmake/config/ipcp/*.cmake files so they are known when generating config.h. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Refactor CMake back to in-tree CMakeListsDimitri Staessens2026-02-139-76/+205
| | | | | | | | | | | | | | | | | | | | | | This moves the build definitions back to src/ subdirectories (CMakeLists.txt per component). Configuration and dependencies are kept out of tree. Configuration options are bundled into cmake/config/ modules. Dependencies are grouped by component (system/, crypt/, eth/, coverage/, etc.). It now consistently uses target-based commands (target_include_directories, target_link_libraries) instead of global include_directories(). Proper PRIVATE/PUBLIC visibility for executable link libraries. CONFIG_OUROBOROS_DEBUG now properly set based on being a valid debug config (not just checking the string name). It also adds OuroborosTargets export for find_package() support and CMake package config files (OuroborosConfig.cmake) for easier integration with CMake projects. The build logic now follows more idiomatic CMake practices with configuration separated from target definitions. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Add per-user packet poolsDimitri Staessens2026-02-136-24/+128
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The IRMd will now check the user UID and GID for privileged access, avoiding unprivileged users being able to disrupt all IPC (e.g. by shm_open the single pool and corrupting its metadata). Non-privileged users are now limited to a PUP (per-user pool) for sending/receiving packets. It is still created by the IRMd, but owned by the user (uid) with 600 permissions. It does not add additional copies for local IPC between their own processes (i.e. over the local IPCP), but packets between processes owned by a different user or destined over the network (other IPCPs) will incur a copy when crossing the PUP / PUP or the PUP / GSPP boundary. Privileged users and users in the ouroboros group still have direct access to the GSPP (globally shared private pool) for packet transfer that will avoid additional copies when processing packets between processes owned by different users and to the network. This aligns the security model with UNIX trust domains defined by UID and GID by leveraging file permission on the pools in shared memory. ┌─────────────────────────────────────────────────────────────┐ │ Source Pool │ Dest Pool │ Operation │ Copies │ ├─────────────────────────────────────────────────────────────┤ │ GSPP │ GSPP │ Zero-copy │ 0 │ │ PUP.uid │ PUP.uid │ Zero-copy │ 0 │ │ PUP.uid1 │ PUP.uid2 │ memcpy() │ 1 │ │ PUP.uid │ GSPP │ memcpy() │ 1 │ │ GSPP │ PUP.uid │ memcpy() │ 1 │ └─────────────────────────────────────────────────────────────┘ This also renames the struct ai ("application instance") in dev.c to struct proc (process). Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Replace rdrbuff with a proper slab allocatorDimitri Staessens2026-01-2613-162/+148
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a first step towards the Secure Shared Memory (SSM) infrastructure for Ouroboros, which will allow proper resource separation for non-privileged processes. This replaces the rdrbuff (random-deletion ring buffer) PoC allocator with a sharded slab allocator for the packet buffer pool to avoid the head-of-line blocking behaviour of the rdrb and reduce lock contention in multi-process scenarios. Each size class contains multiple independent shards, allowing parallel allocations without blocking. - Configurable shard count per size class (default: 4, set via SSM_POOL_SHARDS in CMake). The configured number of blocks are spread over the number of shards. As an example: SSM_POOL_512_BLOCKS = 768 blocks total These 768 blocks are shared among 4 shards (not 768 × 4 = 3072 blocks) - Lazy block distribution: all blocks initially reside in shard 0 and naturally migrate to process-local shards upon first allocation and subsequent free operations - Fallback with work stealing: processes attempt allocation from their local shard (pid % SSM_POOL_SHARDS) first, then steal from other shards if local is exhausted, eliminating fragmentation while maintaining low contention - Round-robin condvar signaling: blocking allocations cycle through all shard condition variables to ensure fairness - Blocks freed to allocator's shard: uses allocator_pid to determine target shard, enabling natural load balancing as process allocation patterns stabilize over time Maintains existing robust mutex semantics including EOWNERDEAD handling for dead process recovery. Internal structures exposed in ssm.h for testing purposes. Adds some tests (pool_test, pool_sharding_test.c. etc) verifying lazy distribution, migration, fallback stealing, and multiprocess behavior. Updates the ring buffer (rbuff) to use relaxed/acquire/release ordering on atomic indices. The ring buffer requires the (robust) mutex to ensure cross-structure synchronization between pool buffer writes and ring buffer index publication. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Add an option for container compatibilityDimitri Staessens2026-01-193-0/+13
| | | | | | | | | This adds a BUILD_CONTAINER option that disables some features that require elevated privileges like setting thread priorities, which might not be supported in docker environments. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Add post-quantum cryptography supportDimitri Staessens2026-01-196-10/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This adds initial support for runtime-configurable encryption and post-quantum Key Encapsulation Mechanisms (KEMs) and authentication (ML-DSA). Supported key exchange algorithms: ECDH: prime256v1, secp384r1, secp521r1, X25519, X448 Finite Field DH: ffdhe2048, ffdhe3072, ffdhe4096 ML-KEM (FIPS 203): ML-KEM-512, ML-KEM-768, ML-KEM-1024 Hybrid KEMs: X25519MLKEM768, X448MLKEM1024 Supported ciphers: AEAD: aes-128-gcm, aes-192-gcm, aes-256-gcm, chacha20-poly1305 CTR: aes-128-ctr, aes-192-ctr, aes-256-ctr Supported HKDFs: sha256, sha384, sha512, sha3-256, sha3-384, sha3-512, blake2b512, blake2s256 Supported Digests for DSA: sha256, sha384, sha512, sha3-256, sha3-384, sha3-512, blake2b512, blake2s256 PQC support requires OpenSSL 3.4.0+ and is detected automatically via CMake. A DISABLE_PQC option allows building without PQC even when available. KEMs differ from traditional DH in that they require asymmetric roles: one party encapsulates to the other's public key. This creates a coordination problem during simultaneous reconnection attempts. The kem_mode configuration parameter resolves this by pre-assigning roles: kem_mode=server # Server encapsulates (1-RTT, full forward secrecy) kem_mode=client # Client encapsulates (0-RTT, cached server key) The enc.conf file format supports: kex=<algorithm> # Key exchange algorithm cipher=<algorithm> # Symmetric cipher kdf=<KDF> # Key derivation function digest=<digest> # Digest for DSA kem_mode=<mode> # Server (default) or client none # Disable encryption The OAP protocol is extended to negotiate algorithms and exchange KEX data. All KEX messages are signed using existing authentication infrastructure for integrity and replay protection. Tests are split into base and _pqc variants to handle conditional PQC compilation (kex_test.c/kex_test_pqc.c, oap_test.c/oap_test_pqc.c). Bumped minimum required OpenSSL version for encryption to 3.0 (required for HKDF API). 1.1.1 is long time EOL. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Add option to toggle Ouroboros logging in testsDimitri Staessens2026-01-194-0/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | The test output is a bit polluted with logs originating fomr the logging system, e.g.: 23: test_bind_prog started. 23: ==16636== reg/name(DB): Add prog reg_test to name testname. 23: ==16636== reg(EE): Removing from names. 23: test_bind_prog succeeded. This adds a flag DISABLE_TEST_LOGGING that suppresses log_* output in tests to keep them clean: 23: test_bind_prog started. 23: test_bind_prog succeeded. The status is printed in CMake output: -- Ouroboros logging in test output disabled -- Ouroboros logging in test output enabled By default the flag is ON (clean test output). Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Refactor CMake modulesDimitri Staessens2026-01-0710-426/+14
| | | | | | | | | This moves the CMake build logic out of the source tree and splits it up into a more modular form. The tests now have a CMakeLists.txt file in their respective source directory. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Initialize mgmt frames in eth/udpDimitri Staessens2026-01-072-0/+12
| | | | | | | | | | The eth and udp layer management frames/packets contain some unused fields which were not cleared after malloc. In a future update, the unused fields will be removed from the packets, but for now, we can just zero these after malloc. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Add build_tests targetThijs Paelman2025-11-213-3/+3
| | | | | | | | | This intermediate target only builds all the tests, it doesn't run them. It is added for clarifying the different steps involved in testing. The 'check' target still builds AND runs the tests as before. Signed-off-by: Thijs Paelman <thijs@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Include tests in 'all' targetThijs Paelman2025-11-073-3/+3
| | | | | | | | | | | | When BUILD_TESTING=ON, then the default 'all' target will now build also the tests. This behaviour could be controlled by an extra variable (see https://stackoverflow.com/a/42235335), but this increases complexity without many benefits. Signed-off-by: Thijs Paelman <thijs@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Only add tests when BUILD_TESTING is ONThijs Paelman2025-11-072-4/+8
| | | | | | | By default, BUILD_TESTING = ON due to the inclusion of the CTest module. Signed-off-by: Thijs Paelman <thijs@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Fix the flow_join operationDimitri Staessens2025-09-243-20/+46
| | | | | | | | | This fixes a regression in the code path for joining a broadcast Layer. It deprecates the qos parameter on flow_join, as the QoS is implied by the broadcast Layer itself. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Move encryption control from QoS to nameDimitri Staessens2025-09-104-40/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This removes the flow encryption option (cypher_s) from the qosspec. The configuration file is configured in the security options (default /etc/ouroboros/security/). For this poc, encryption can be disabled client or server side by putting an enc.cfg file. If that file is present in the client folder, the client will require encryption. If that file is present on the server side, the server will require encryption and reject non-encrypted flows. Encryption is now configured outside of any application control. Example: /etc/ouroboros/security/client/oping/enc.cfg exists: irmd(II): Encryption enabled for oping. irmd(DB): File /etc/ouroboros/security/client/oping/crt.pem does not exist. irmd(II): No security info for oping. irmd(DB): Generated ephemeral keys for 87474. irmd/oap(PP): OAP_HDR [caf203681d997941 @ 2025-09-02 17:08:05 (UTC) ] --> irmd/oap(PP): Certificate: <none> irmd/oap(PP): Ephemeral Public Key: [91 bytes] irmd/oap(PP): Data: <none> irmd/oap(PP): Signature: <none> Example: /etc/ouroboros/security/client/oping/enc.cfg does not exist: irmd(II): Allocating flow for 87506 to oping. irmd(DB): File /etc/ouroboros/security/client/oping/enc.cfg does not exist. irmd(DB): File /etc/ouroboros/security/client/oping/crt.pem does not exist. irmd(II): No security info for oping. irmd/oap(PP): OAP_HDR [e84bb9d7c3d9c002 @ 2025-09-02 17:08:30 (UTC) ] --> irmd/oap(PP): Certificate: <none> irmd/oap(PP): Ephemeral Public Key: <none> irmd/oap(PP): Data: <none> irmd/oap(PP): Signature: <none> Example: /etc/ouroboros/security/server/oping/enc.cfg exists: irmd(II): Flow request arrived for oping. irmd(DB): IPCP 88112 accepting flow 7 for oping. irmd(II): Encryption enabled for oping. irmd(DB): File /etc/ouroboros/security/server/oping/crt.pem does not exist. irmd(II): No security info for oping. irmd/oap(PP): OAP_HDR [3c717b3f31dff8df @ 2025-09-02 17:13:06 (UTC) ] <-- irmd/oap(PP): Certificate: <none> irmd/oap(PP): Ephemeral Public Key: <none> irmd/oap(PP): Data: <none> irmd/oap(PP): Signature: <none> irmd(WW): Encryption required but no key provided. The server side will pass the ECRYPT to the client: $ oping -l Ouroboros ping server started. Failed to accept flow: -1008 $ oping -n oping -c 1 Failed to allocate flow: -1008. Encryption on flows can now be changed at runtime without needing to touch/reconfigure/restart the process. Note: The ECRYPT result is passed on via the flow allocator responses through the IPCP (discovered/fixed some endianness issues), but the reason for rejecting the flow can be considered N+1 information... We may move that information up into the OAP header at some point. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Add ipcpd over UDP/IPv6Dimitri Staessens2025-09-1010-184/+339
| | | | | | | | | | This adds an IPCP that runs over UDP/IPv6. It's structured like the eth-dix and eth-llc in that it builds two separate binaries: ipcpd-udp4 and ipcpd-udp6. The IRM CLI is backwards compatible in that type 'udp' will resolve to type 'udp4'. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Fix missing return in DHTDimitri Staessens2025-08-241-2/+6
| | | | | | | The dht_kv_respond_req had a missing return statement. I'm not sure why the double mutex_unlock() never caused havoc in testing. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
* ipcpd: Start the connmgr firstDimitri Staessens2025-08-241-9/+9
| | | | | | | | | The DT component (which starts the routing component) and enrollment component rely on the connmgr, and when enrolling larger networks, the link state component sometimes fails to connect because the conngmr is not fully started yet. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
* build: Add some hints for scan-buildDimitri Staessens2025-08-231-0/+3
| | | | | | | | The scan-build tool was pointing out some potential issues that were understood or false positives. Added some asserts so scan-build can complete successfully without these warnings. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
* ipcpd: Fix printf formatting in tests on raspbianDimitri Staessens2025-08-231-1/+1
| | | | | | Fixes some printf formatting, which was failing the build on raspbian. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
* ipcpd: Simplify enroll and connmgr startup/shutdownDimitri Staessens2025-08-232-33/+7
| | | | | | | There's not need to keep these states as they always follow the init/start/stop/fini flow. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
* ipcpd: Add cleanup of DHT replication listsDimitri Staessens2025-08-231-0/+11
| | | | | | | The replication/republication lists could leak on shutdown. Added cleanup handlers for them. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
* ipcpd: Fix request handling at shutdownDimitri Staessens2025-08-233-20/+24
| | | | | | | | | | | | | | | | | The IPCP states were not entirely correct causing some operations to be serviced during shutdown. This caused some use-after-free in the pff. States in the IPCP are now correctly set. IRMd states updated to the same strategy. The IRMd registry tracks if the IPCP was ENROLLED or BOOTSTRAPPED, the IPCP just goes to OPERATIONAL. IPCP state diagram:: NULL -> init() -> INIT -> start() -> BOOT -> bootstrap/enroll() -> OPERATIONAL -> shutdown() -> SHUTDOWN -> stop_components() -> BOOT -> stop() -> INIT -> fini() -> NULL Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
* irmd: Add flow authenticationDimitri Staessens2025-08-182-8/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This adds initial implementation of peer authentication as part of flow allocation. If credentials are not provided, this will be accepted and logged as info that the flow is not authenticated. Certificates and keys are passed as .pem files. The key file should not be encrypted, else the IRMd will open a prompt for the password. The default location for these .pem files is in /etc/ouroboros/security. It is strongly recommended to make this directory only accessible to root. ├── security │ ├── cacert │ │ └── ca.root.o7s.crt.pem │ ├── client │ │ ├── <name> │ │ | ├── crt.pem │ │ | └── key.pem │ │ └── <name> | | ├──... | | │ ├── server │ │ ├── <name> │ │ | ├── crt.pem │ │ | └── key.pem │ │ └── <name> | | ├── ... | | │ └── untrusted │ └── sign.root.o7s.crt.pem Trusted root CA certificates go in the /cacert directory, untrusted certificates for signature verification go in the /untrusted directory. The IRMd will load these certificates at boot. The IRMd will look for certificates in the /client and /server directories. For each name a subdirectory can be added and the credentials in that directory are used to sign the OAP header for flows at flow_alloc() on the client side and flow_accept() on the server side. These defaults can be changed at build time using the following variables (in alphabetical order): OUROBOROS_CA_CRT_DIR /etc/ouroboros/security/cacert OUROBOROS_CLI_CRT_DIR /etc/ouroboros/security/client OUROBOROS_SECURITY_DIR /etc/ouroboros/security OUROBOROS_SRV_CRT_DIR /etc/ouroboros/security/server OUROBOROS_UNTRUSTED_DIR /etc/ouroboros/security/untrusted The directories for the names can also be configured at IRMd boot using the configuraton file and at runtime when a name is created using the "irm name create" CLI tool. The user needs to have permissions to access the keyfile and certificate when specifying the paths with the "irm name create" CLI tool. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
* ipcpd: Fix addresses in RIB entriesDimitri Staessens2025-08-183-6/+6
| | | | | | | | | The entries of the RIB were broken as some paths in FUSE were checked against the old entry format. Updated the address format to use a dot to avoid escaping colons and spaces and be friendlier to command line tools such as 'cat'. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
* ipcpd: Configure link-state at bootstrapDimitri Staessens2025-08-186-131/+151
| | | | | | | | | The link-state component had some values defined in the source such as link-state advertisement interval, link timeout period and the PFF recalculation time. These can now be configured from the config file or via "irm ipcp bootstrap" on the command line. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
* ipcpd: Fix readdir() not initializing ptrDimitri Staessens2025-08-115-9/+14
| | | | | | | | | Some IPCP (sub)components returned successfully with 0 entries but did not initialize the buf ptr when the RIB has no entries, causing a SEGV on free() in the RIB. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Remove old IPCP_CONN_WAIT_DIR build optionDimitri Staessens2025-08-115-9/+4
| | | | | | | | The IPCP_CONN_WAIT_DIR build option is not needed anymore with the recent update to the DHT. Also cleans up some logging in the IPCP. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Fix shutdown of link-state routingDimitri Staessens2025-08-116-34/+85
| | | | | | | | | | | | | | | | | | | | The link_state component tried to unregister from the notifier while it had threads running. The deadlock happens when notifier_event had a rdlock trying to delete a neighbour, while notifier_unreg tries to take the write lock. And the delete can't complete in the notifier. https://tree.taiga.io/project/dstaesse-ouroboros/us/113 We need to make sure that all threads are stopped before unregistering from the notifier. Updated link_state to use the start/stop() paradigm and not create/cancel threads within init/fini(). Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Fix DHT test initializer compilation errorDimitri Staessens2025-08-111-4/+11
| | | | | | | | dht_test.c:167:48: error: initializer element is not a compile-time constant static struct dir_dht_config test_dht_config = default_dht_config; Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Add protocol debug option for link-stateDimitri Staessens2025-08-066-138/+172
| | | | | | | | | | | | | | | | | | | | | | | | | | The link-state routing component now has a protocol debugging option, activated by enabling the DEBUG_PROTO_LS flag at build time in a debug build. Example output (sender and receiver): LSU [81:8a:1f:9b -- 50:c6:2d:03 seq: 000000000] --> 50:c6:2d:03 LSU [81:8a:1f:9b -- 50:c6:2d:03 seq: 000000000] <-- 50:c6:2d:03 In larger networks, forwarded LSUs are marked as such: LSU [ee:53:ae:f8 -- e5:33:e4:8d seq: 000000006] --> e5:33:e4:8d [forwarded] This also aligns the address printing using a similar ethernet-like formatting such as the DHT component. Small code cleanup in the graph component. Note: eventually the link state dissemination should move to a broadcast Layer instead of the link state component doing the forwarding. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Update DHT for unicast layerDimitri Staessens2025-08-0626-2220/+5289
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a rewrite of the DHT for name-to-address resolution in the unicast layer. It is now integrated as a proper directory policy. The dir_wait_running function is removed, instead the a DHT peer is passed on during IPCP enrolment. Each DHT request/response gets a random 64-bit ID ('cookie'). DHT messages to the same peer are deduped, except in the case when the DHT is low on contacts. In that case, it will contact the per it received at enrolment for more contacts. To combat packet loss, these messages are not deduped by means of a 'magic cookie', chosen at random when the DHT starts. The DHT parameters (Kademlia) can be set using the configfile or the IRM command line tools: if DIRECTORY_POLICY == DHT [dht_alpha <search factor> (default: 3)] [dht_k <replication factor> (default: 8)] [dht_t_expire <expiration (s)> (default: 86400)] [dht_t_refresh <contact refresh (s)> (default: 900)] [dht_t_replicate <replication (s)> (default: 900)] This commit also adds support for a protocol debug level (PP). Protocol debugging for the DHT can be enabled using the DEBUG_PROTO_DHT build flag. The DHT has the following message types: DHT_STORE, sent to k peers. Not acknowledged. DHT_STORE --> [2861814146dbf9b5|ed:d9:e2:c4]. key: bcc236ab6ec69e65 [32 bytes] val: 00000000c4e2d9ed [8 bytes] exp: 2025-08-03 17:29:44 (UTC). DHT_FIND_NODE_REQ, sent to 'alpha' peers, with a corresponding response. This is used to update the peer routing table to iteratively look for the nodes with IDs closest to the requested key. DHT_FIND_NODE_REQ --> [a62f92abffb451c4|ed:d9:e2:c4]. cookie: 2d4b7acef8308210 key: a62f92abffb451c4 [32 bytes] DHT_FIND_NODE_RSP <-- [2861814146dbf9b5|ed:d9:e2:c4]. cookie: 2d4b7acef8308210 key: a62f92abffb451c4 [32 bytes] contacts: [1] [a62f92abffb451c4|9f:0d:c1:fb] DHT_FIND_VALUE_REQ, sent to 'k' peers, with a corresponding response. Used to find a value for a key. Will also send its closest known peers in the response. DHT_FIND_VALUE_REQ --> [2861814146dbf9b5|ed:d9:e2:c4]. cookie: 80a1adcb09a2ff0a key: 42dee3b0415b4f69 [32 bytes] DHT_FIND_VALUE_RSP <-- [2861814146dbf9b5|ed:d9:e2:c4]. cookie: 80a1adcb09a2ff0a key: 42dee3b0415b4f69 [32 bytes] values: [1] 00000000c4e2d9ed [8 bytes] contacts: [1] [a62f92abffb451c4|9f:0d:c1:fb] Also removes ubuntu 20 from appveyor config as it is not supported anymore. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix flow timeouts after flow allocationDimitri Staessens2025-08-061-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | There were two timeout bugs in the flow allocation steps. Found these when debugging why some links were always timing out in one direction. The first bug only affects flows going through the connection manager in the IPCP (such as the management flow used by the link state routing component. The connection manager was setting a timeout on the flow for its handling connection establishment, but didn't reset that timeout before handing the flow to the internal component after the CEP was complete. The link-state routing component was showing flow read timeouts (ETIMEDOUT) without setting one. This was not causing the links to time out. The second one was that the IPCP was keeping the qosspec from on the np1 flow, which, when the qosspec requested for the applicatoin had a keepalive set, would always time out. This bug was the root cause for some link advertisements not to be read and links to time out in the link-state routing component. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Get correct eth MTU on MacOS and BSDDimitri Staessens2025-08-011-129/+234
| | | | | | | | The device MTU was not retrieved on those platforms. Fixed that while refactoring the bootstrap function. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>