summaryrefslogtreecommitdiff
path: root/cmake/config
Commit message (Collapse)AuthorAgeFilesLines
* irmd: Deliver flow re-keyingDimitri Staessens4 days1-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Re-key each encrypted flow's batch root periodically so a long-lived flow never exhausts or over-uses a single root. The IRMd re-runs the OAP exchange with the peer IRMd over the flow-update relay. The per-flow re-keying state is tracked in the registry (reg_flow). A re-key delivers one root seed from the OAP exchange. keyrot immediately HKDF-expands it into 128 node keys (KR_NODES_SZ = 128 × 32 B) and wipes the root. Then each of the 128 node keys is itself a root → HKDF-expanded into 64 (2^KEY_NODE_BITS) leaf keys, forked per direction; each leaf key is the actual AEAD key, good for 2^20 packets (the low counter bits are its nonce/seq). If the number of keys runs low, a re-key will be triggered (KEY_REKEY_WATERMARK). The rekey is signalled out of band to the application. The rbuff ACL is generalized into a flags word, so an RB_REKEY bit rides alongside the access RB_RD/RB_WR and FLOWDOWN/FLOWPEER bits. The RD and WR bits are revised ditching the fcntl historical weirdness. The seed is pulled via flow_read/flow_write, installed with crypt_rekey(). TX holds the old epoch until the peer is observed on the new one (or a grace deadline elapses), promoted from both the read and write paths so a recv-mostly flow still advances. Also fix the FLOW_ACCEPT and FLOW_ALLOC handlers, which on a key-buffer allocation failure returned from inside the cleanup-push region: that leaked the reply message and skipped both the stack-key scrub and the cleanup pop. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Harden symmetric-key rotationDimitri Staessens4 days3-5/+47
| | | | | | | | | | | | | | | | | | Flow crypto signalled rotation with a single phase-parity bit, so a loss burst that hid an even number of rotations went unnoticed and wedged the flow for good. Each packet now carries a small cleartext selector naming its key directly, so a receiver that falls behind recovers on the next packet instead of getting stuck. The selector also serves as the AEAD nonce and is authenticated as associated data (AAD). Key rotation moves into a new backend-agnostic keyrot module that rotates sub-keys to bound AEAD usage while preserving forward secrecy. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Bound the OAP replay cacheDimitri Staessens4 days1-0/+2
| | | | | | | | | | | | | | | | | Replace the linked-list cache with three timestamp-generation hash buckets, each capped at OAP_REPLAY_MAX entries. A bucket is an open-addressed hash set whose slots count as live only while slot.gen equals the bucket generation, so a stale bucket clears in O(1) by bumping its generation instead of being scanned and pruned. On overflow the cache fails closed - it rejects the header rather than evicting the oldest entry. Under flood, dropping a genuine entry would let that header be replayed, so refusing new entries is the safer degradation than evict-oldest (fail-open) behaviour. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Specify peer authentication contractDimitri Staessens4 days1-0/+2
| | | | | | | | | | | | | | | | | | | | | | OAP accepted requests and responses without a certificate even when the peer was expected to authenticate. An on-path attacker could strip the certificate and signature from a flow allocation response and substitute its own key exchange, silently downgrading the handshake to unauthenticated. Add an auth=required|optional policy to enc.conf, enforced per role: a client config requires the server to present a valid certificate, a server config requires the same from the client. Default is required for client side (https), optional server side. The client side default can be changed via OAP_CLIENT_AUTH_DEFAULT for testing. Replace the bare 'none' keyword with encryption=none, which disables encryption only: the digest and the authentication policy are kept, so authenticated but unencrypted flows can be configured. Configs using bare 'none' are now rejected. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Reclaim aged leaked ssm pool blocksDimitri Staessens2026-06-031-0/+2
| | | | | | | | | | | The reclaim_pid_from_sc() function reaped any block allocated with refcount from a dead PID, but cross-process hand-offs can leave a block briefly allocated by the producer while a live consumer still holds it. This skips reclaim within SSM_POOL_RECLAIM_AGE_S (default 60s) so in-flight hand-offs survive a producer crash. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Decouple rbuff size from RQ sizeDimitri Staessens2026-06-031-12/+2
| | | | | | | | The rbuff size was at one point coupled to RQ size for debugging, reverting. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Fully gate fa/dt RIB ops on IPCP_FLOW_STATStestingDimitri Staessens2026-05-271-2/+7
| | | | | | | | | | | | | The previous shape registered no-op _rib_read / _rib_readdir / _rib_getattr handlers when IPCP_FLOW_STATS was off, and there was a bug where *buf was not set in the no-op causing free on an uninitialized pointer. IPCP_FLOW_STATS was referenced by config.h.in but the declaration was lost during the CMake refactor. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Update FRCP implementationDimitri Staessens2026-05-203-19/+66
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The Flow and Retransmission Control Protocol (FRCP) runs end-to-end between two peers over a flow. It provides reliability, in-order delivery, flow control, and liveness. Note that congestion avoidance is orthogonal to FRCP and handled in the IPCP. A fixed 16-octet header, network byte order, is prefixed to every FRCP packet: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | flags | hcs | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | window | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | seqno | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ackno | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | payload (variable) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ hcs is a CRC-16-CCITT-FALSE checksum over the PCI (and the stream extension when present), verified before any flag-driven dispatch. A single packet can simultaneously carry DATA + ACK + FC + RXM by OR-ing flag bits. An optional CRC trailer covers the body on DATA when qs.ber == 0, and on every SACK packet; an optional AEAD wrap (per-flow keys) sits outermost. Flag bits (MSB-first; bits 13..15 reserved, MUST be zero): +------+--------+--------+----------------------------------------+ | Bit | Mask | Name | Meaning | +------+--------+--------+----------------------------------------+ | 0 | 0x8000 | DATA | Carries caller payload | | 1 | 0x4000 | DRF | Start of a fresh data run | | 2 | 0x2000 | ACK | ackno field valid | | 3 | 0x1000 | NACK | Pre-DRF nudge (seqno informational) | | 4 | 0x0800 | FC | window field valid (rwe advertisement) | | 5 | 0x0400 | RDVS | Rendezvous probe (window-closed) | | 6 | 0x0200 | FFGM | First Fragment of a multi-fragment SDU | | 7 | 0x0100 | LFGM | Last Fragment of a multi-fragment SDU | | 8 | 0x0080 | RXM | Retransmission | | 9 | 0x0040 | SACK | Block list follows in payload | | 10 | 0x0020 | RTTP | RTT probe / echo (payload follows) | | 11 | 0x0010 | KA | Keepalive | | 12 | 0x0008 | FIN | End of stream marker | | 13-15| -- | -- | Reserved (MUST be zero) | +------+--------+--------+----------------------------------------+ (FFGM, LFGM) encodes the fragment role of a DATA packet (SCTP-style B/E): 11=SOLE, 10=FIRST, 00=MID, 01=LAST. Each fragment carries its own seqno; Retransmission recovers fragments individually, reassembly runs at consume time. In stream mode FFGM/LFGM are unused; per-byte position is carried by the stream extension below and end-of-stream is signalled by FIN on a 0-byte DATA packet. SACK payload (FRCT_ACK | FRCT_FC | FRCT_SACK): 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | n_blocks | padding (2 octets) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | start[0] | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | end[0] | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ... n_blocks pairs total ... Each block describes a *present* (received) range strictly above the cumulative ACK in the PCI ackno. D-SACK (RFC 2883) is signalled in-band as block[0] - no flag bit, no extra framing - and consumed by the RACK reo_wnd_mult scaler (RFC 8985 sec. 7.2). RTTP payload (FRCT_RTTP only; 24 octets): 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | probe_id | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | echo_id | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + nonce (16 octets, echoed verbatim) + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Stream PCI extension (in_order == STREAM only; 8 octets after the base PCI on every DATA packet): 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | start | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | end | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ start, end are monotonic 32-bit byte offsets; end - start equals the on-wire payload length. Stream mode is negotiated at flow allocation; the extension is present iff stream mode is in use, never on a per-packet basis. Service modes are an orthogonal (in_order, loss, ber) vector selected at flow_alloc; the cubes above map to the axes: +----------------+---------+------+-----+-----------------------+ | Cube | in_order| loss | ber | Engaged | +----------------+---------+------+-----+-----------------------+ | qos_raw | 0 | 1 | 1 | Raw passthrough | | qos_raw_safe | 0 | 1 | 0 | Raw + CRC trailer | | qos_rt | 1 | 1 | 1 | FRCP, no FRTX, no CRC | | qos_rt_safe | 1 | 1 | 0 | FRCP, no FRTX, CRC | | qos_msg | 1 | 0 | 0 | FRCP + FRTX | | qos_stream | 2 | 0 | 0 | FRCP + FRTX, stream | +----------------+---------+------+-----+-----------------------+ in_order=0 sends raw datagrams with no PCI (UDP-equivalent); in_order=1 engages FRCP with SDU framing; in_order=2 (stream) requires loss=0 and is rejected otherwise. loss=0 engages the FRTX retransmit machinery. ber=0 appends the CRC-32 trailer; QOS_DISABLE_CRC at build time forces ber=1 for development. Encryption is a separate per-flow attribute layered as an AEAD wrap outside the FRCP packet. Heritage: delta-t (Watson 1981) supplies timer-based connection management - no SYN/FIN handshake, the DRF marker, the t_mpl / t_a / t_r timers. RINA (Day 2008) supplies the unified flow_alloc(name, qos, ...) primitive and the orthogonal QoS-cube axes. Loss detection follows TCP/QUIC practice (RFCs 2018, 2883, 6582, 6298, 8985); RTT probing is nonce-authenticated like QUIC PATH_CHALLENGE. Adds oftp, a minimal file-transfer tool over an FRCP stream flow. The client reads from stdin or --in FILE and writes through a flow_alloc(qos_stream); the server (--listen) calls flow_accept and writes to stdout or --out FILE. Both sides compute a CRC-64/NVMe over the bytes they handle and print the result. The server rejects flows whose negotiated qs.in_order != STREAM. Two FRCP knobs are exposed via env vars on either side: OFTP_FRCT_RTO_MIN fccntl FRCTSRTOMIN (ns) OFTP_FRCT_STREAM_RING_SZ fccntl FRCTSRRINGSZ (octets) The ocbr_client gains an OCBR_QOS env var to pick the cube the client uses for flow_alloc; recognised values are raw, safe, rt, rt_safe, msg, stream. Unknown values fall back to raw with a warning on stderr. Without the env set behaviour is unchanged. Removes the deprecated lib/timerwheel.c Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Remove deprecated cmake optionsDimitri Staessens2026-05-202-4/+0
| | | | | | | RXM_BUFFER_ON_HEAP and SSM_POOL_BLOCKS were no longer used. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd-eth: Tune raw sockets and retry queriesDimitri Staessens2026-05-202-2/+6
| | | | | | | | | | | | | | | | | | | 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 Staessens2026-05-204-0/+39
| | | | | | | | | 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 Staessens2026-05-201-3/+3
| | | | | | | | | 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: Expose ipcpd-eth flow statistics via RIBDimitri Staessens2026-05-201-0/+10
| | | | | | | | | | | | | 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>
* cmake: Add CPU feature detection helperDimitri Staessens2026-05-061-0/+11
| | | | | | | | | | | | Add cmake/utils/CPUUtils.cmake providing detect_cpu_feature() plus detect_pclmul() and detect_pmull() that compile-test for x86 PCLMULQDQ+SSE4.1 and aarch64 FEAT_PMULL respectively. This will be useful for hardware accelerated CRC64/NVMe integrity checks. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Allow direct rbuff between local processesDimitri Staessens2026-02-221-0/+4
| | | | | | | | | | | | | | | | | | | | | | This allows bypassing the IPCP for local processes that share the same packet pool, lowering latency between processes to comparable levels as Unix sockets (RTT in the order of a microsecond). For local processes, no IPCPs are needed: $ irm b prog oping n oping $ oping -l Ouroboros ping server started. New flow 64. Received 64 bytes on fd 64. The direct IPC can be disabled with the DISABLE_DIRECT_IPC build flag. Note that this is needed for rumba 'local' experiments to emulate network topologies. Without this flag all processes will just communicate directly. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Set FUSE_PREFIX in fuse.cmakeDimitri Staessens2026-02-181-6/+0
| | | | | | | | The FUSE_PREFIX was set in global.cmake, but before HAVE_FUSE was defined. The FUSE_PREFIX should be set in fuse.cmake. 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-0/+12
| | | | | | | | | | | | | | | | 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: Fix assertion tests core dump state messageDimitri Staessens2026-02-131-3/+3
| | | | | | | | The message for enabled/disabled state of the assertion tests core dumping was reversed. 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-1311-0/+413
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>