summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt54
-rw-r--r--cmake/OuroborosConfig.cmake.in23
-rw-r--r--cmake/compiler.cmake38
-rw-r--r--cmake/config/global.cmake45
-rw-r--r--cmake/config/ipcp/broadcast.cmake4
-rw-r--r--cmake/config/ipcp/common.cmake43
-rw-r--r--cmake/config/ipcp/eth.cmake15
-rw-r--r--cmake/config/ipcp/local.cmake7
-rw-r--r--cmake/config/ipcp/udp.cmake9
-rw-r--r--cmake/config/ipcp/unicast.cmake12
-rw-r--r--cmake/config/irmd.cmake36
-rw-r--r--cmake/config/lib.cmake (renamed from cmake/lib/lib.cmake)46
-rw-r--r--cmake/config/ssm.cmake131
-rw-r--r--cmake/config/tests.cmake17
-rw-r--r--cmake/dependencies.cmake54
-rw-r--r--cmake/dependencies/coverage/gcov.cmake21
-rw-r--r--cmake/dependencies/coverage/lcov.cmake (renamed from cmake/dependencies/lcov.cmake)18
-rw-r--r--cmake/dependencies/crypt/libgcrypt.cmake55
-rw-r--r--cmake/dependencies/crypt/openssl.cmake (renamed from cmake/dependencies/openssl.cmake)29
-rw-r--r--cmake/dependencies/eth/bpf.cmake (renamed from cmake/dependencies/bpf.cmake)14
-rw-r--r--cmake/dependencies/eth/netmap.cmake (renamed from cmake/dependencies/netmap.cmake)10
-rw-r--r--cmake/dependencies/eth/rawsockets.cmake (renamed from cmake/dependencies/rawsockets.cmake)10
-rw-r--r--cmake/dependencies/explicit_bzero.cmake1
-rw-r--r--cmake/dependencies/fuse.cmake23
-rw-r--r--cmake/dependencies/gcov.cmake11
-rw-r--r--cmake/dependencies/irmd/libtoml.cmake29
-rw-r--r--cmake/dependencies/libgcrypt.cmake31
-rw-r--r--cmake/dependencies/libtoml.cmake5
-rw-r--r--cmake/dependencies/sysrandom.cmake21
-rw-r--r--cmake/dependencies/system/explicit_bzero.cmake4
-rw-r--r--cmake/dependencies/system/fuse.cmake44
-rw-r--r--cmake/dependencies/system/libraries.cmake17
-rw-r--r--cmake/dependencies/system/protobufc.cmake (renamed from cmake/dependencies/protobufc.cmake)10
-rw-r--r--cmake/dependencies/system/robustmutex.cmake (renamed from cmake/dependencies/robustmutex.cmake)10
-rw-r--r--cmake/dependencies/system/sysrandom.cmake14
-rw-r--r--cmake/dependencies/systemlibraries.cmake20
-rw-r--r--cmake/dependencies/udp/ddns.cmake31
-rw-r--r--cmake/doc.cmake14
-rw-r--r--cmake/include.cmake8
-rw-r--r--cmake/install.cmake87
-rw-r--r--cmake/ipcp.cmake10
-rw-r--r--cmake/ipcp/broadcast.cmake22
-rw-r--r--cmake/ipcp/eth.cmake42
-rw-r--r--cmake/ipcp/ipcp.cmake60
-rw-r--r--cmake/ipcp/local.cmake11
-rw-r--r--cmake/ipcp/udp.cmake51
-rw-r--r--cmake/ipcp/unicast.cmake50
-rw-r--r--cmake/irmd.cmake125
-rw-r--r--cmake/lib.cmake11
-rw-r--r--cmake/lib/common.cmake124
-rw-r--r--cmake/lib/dev.cmake37
-rw-r--r--cmake/lib/irm.cmake34
-rw-r--r--cmake/lib/ssm.cmake89
-rw-r--r--cmake/package.cmake12
-rw-r--r--cmake/tests.cmake30
-rw-r--r--cmake/tools.cmake8
-rw-r--r--cmake/tools/irm.cmake33
-rw-r--r--cmake/tools/obc.cmake4
-rw-r--r--cmake/tools/ocbr.cmake4
-rw-r--r--cmake/tools/oecho.cmake4
-rw-r--r--cmake/tools/operf.cmake4
-rw-r--r--cmake/tools/oping.cmake4
-rw-r--r--cmake/tools/ovpn.cmake6
-rw-r--r--cmake/tools/tools.cmake8
-rw-r--r--cmake/utils/AddCompileFlags.cmake21
-rw-r--r--cmake/utils/CMakeUninstall.cmake.in36
-rw-r--r--cmake/utils/CompilerUtils.cmake10
-rw-r--r--cmake/utils/DebugTargets.cmake16
-rw-r--r--cmake/utils/DisableTestLogging.cmake23
-rw-r--r--cmake/utils/FindProtobufC.cmake36
-rw-r--r--cmake/utils/GenCoverage.cmake6
-rw-r--r--cmake/utils/TestUtils.cmake34
-rw-r--r--include/ouroboros/flow.h2
-rw-r--r--include/ouroboros/ipcp-dev.h6
-rw-r--r--include/ouroboros/local-dev.h8
-rw-r--r--include/ouroboros/proc.h5
-rw-r--r--include/ouroboros/serdes-irm.h5
-rw-r--r--include/ouroboros/ssm_pool.h10
-rw-r--r--include/ouroboros/utils.h6
-rw-r--r--src/ipcpd/CMakeLists.txt30
-rw-r--r--src/ipcpd/broadcast/CMakeLists.txt22
-rw-r--r--src/ipcpd/eth/CMakeLists.txt24
-rw-r--r--src/ipcpd/eth/eth.c5
-rw-r--r--src/ipcpd/ipcp.c56
-rw-r--r--src/ipcpd/local/CMakeLists.txt19
-rw-r--r--src/ipcpd/local/main.c34
-rw-r--r--src/ipcpd/np1.h41
-rw-r--r--src/ipcpd/udp/CMakeLists.txt17
-rw-r--r--src/ipcpd/udp/udp.c5
-rw-r--r--src/ipcpd/unicast/CMakeLists.txt51
-rw-r--r--src/ipcpd/unicast/dir/tests/CMakeLists.txt42
-rw-r--r--src/ipcpd/unicast/fa.c11
-rw-r--r--src/ipcpd/unicast/pff/tests/CMakeLists.txt39
-rw-r--r--src/ipcpd/unicast/routing/tests/CMakeLists.txt37
-rw-r--r--src/irmd/CMakeLists.txt65
-rw-r--r--src/irmd/config.h.in2
-rw-r--r--src/irmd/ipcp.c6
-rw-r--r--src/irmd/main.c87
-rw-r--r--src/irmd/oap/tests/CMakeLists.txt55
-rw-r--r--src/irmd/reg/flow.c1
-rw-r--r--src/irmd/reg/pool.c101
-rw-r--r--src/irmd/reg/pool.h48
-rw-r--r--src/irmd/reg/proc.c10
-rw-r--r--src/irmd/reg/proc.h2
-rw-r--r--src/irmd/reg/reg.c105
-rw-r--r--src/irmd/reg/reg.h9
-rw-r--r--src/irmd/reg/tests/CMakeLists.txt46
-rw-r--r--src/irmd/reg/tests/proc_test.c17
-rw-r--r--src/irmd/reg/tests/reg_test.c33
-rw-r--r--src/lib/CMakeLists.txt160
-rw-r--r--src/lib/crypt.c4
-rw-r--r--src/lib/dev.c689
-rw-r--r--src/lib/frct.c18
-rw-r--r--src/lib/pb/ipcp.proto1
-rw-r--r--src/lib/pb/irm.proto4
-rw-r--r--src/lib/pb/model.proto13
-rw-r--r--src/lib/protobuf.c15
-rw-r--r--src/lib/serdes-irm.c8
-rw-r--r--src/lib/ssm/pool.c231
-rw-r--r--src/lib/ssm/ssm.h.in31
-rw-r--r--src/lib/ssm/tests/CMakeLists.txt15
-rw-r--r--src/lib/ssm/tests/pool_sharding_test.c23
-rw-r--r--src/lib/ssm/tests/pool_test.c32
-rw-r--r--src/lib/tests/CMakeLists.txt18
-rw-r--r--src/lib/timerwheel.c10
-rw-r--r--src/lib/utils.c64
-rw-r--r--src/tools/CMakeLists.txt71
-rw-r--r--src/tools/oping/oping.c11
-rw-r--r--src/tools/oping/oping_client.c149
-rw-r--r--src/tools/oping/oping_server.c5
130 files changed, 2795 insertions, 1875 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2ed52fd2..d225d29d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,4 @@
-cmake_minimum_required(VERSION 2.8.12.2...4.0.3.0)
-cmake_policy(VERSION ${CMAKE_VERSION})
+cmake_minimum_required(VERSION 3.19)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
@@ -7,50 +6,67 @@ project(ouroboros C)
include(GNUInstallDirs)
+include(utils/DebugTargets)
+
include(version)
include(package)
include(compiler)
-if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
- if (APPLE)
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ if(APPLE)
set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE STRING
"Installation Prefix" FORCE)
else()
set(CMAKE_INSTALL_PREFIX "/usr" CACHE STRING
"Installation Prefix" FORCE)
endif()
-endif ()
+endif()
-if (APPLE)
+if(APPLE)
set(CMAKE_MACOSX_RPATH 1)
- include_directories("/usr/local/include/")
+ # Homebrew installs to /usr/local/include on Intel, /opt/homebrew/include on ARM
+ set(APPLE_INCLUDE_DIRS "/usr/local/include" "/opt/homebrew/include"
+ CACHE INTERNAL "Apple system include directories")
endif()
-if (CMAKE_INSTALL_PREFIX STREQUAL "/usr")
+if(CMAKE_INSTALL_PREFIX STREQUAL "/usr")
set(RPATH_PREFIX "")
-else ()
+else()
set(RPATH_PREFIX ${CMAKE_INSTALL_PREFIX})
-endif ()
+endif()
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES
- "${RPATH_PREFIX}/lib" isSystemDir)
-IF ("${isSystemDir}" STREQUAL "-1")
- set(CMAKE_INSTALL_RPATH "${RPATH_PREFIX}/lib")
-ENDIF ("${isSystemDir}" STREQUAL "-1")
+ "${RPATH_PREFIX}/${CMAKE_INSTALL_LIBDIR}" isSystemDir)
+if(isSystemDir STREQUAL "-1")
+ set(CMAKE_INSTALL_RPATH "${RPATH_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
+endif()
include(dependencies)
-include(include)
-include(lib)
-include(ipcp)
-include(irmd)
-include(tools)
+# Configuration options (must be loaded before component modules)
+include(config/global)
+include(config/lib)
+include(config/ssm)
+include(config/irmd)
+include(config/ipcp/common)
+include(config/ipcp/unicast)
+include(config/ipcp/broadcast)
+include(config/ipcp/local)
+include(config/ipcp/eth)
+include(config/ipcp/udp)
+
include(tests)
+include(include)
+add_subdirectory(src/lib)
+add_subdirectory(src/irmd)
+add_subdirectory(src/ipcpd)
+add_subdirectory(src/tools)
+setup_coverage_target()
include(doc)
include(install)
diff --git a/cmake/OuroborosConfig.cmake.in b/cmake/OuroborosConfig.cmake.in
new file mode 100644
index 00000000..41ff7fdd
--- /dev/null
+++ b/cmake/OuroborosConfig.cmake.in
@@ -0,0 +1,23 @@
+# Ouroboros CMake Package Configuration
+#
+# This file allows other CMake projects to find and use Ouroboros libraries
+# via find_package(Ouroboros).
+#
+# Exported targets:
+# Ouroboros::dev - Development library (libouroboros-dev)
+# Ouroboros::irm - IRM management library (libouroboros-irm)
+#
+# Example usage:
+# find_package(Ouroboros REQUIRED)
+# target_link_libraries(myapp Ouroboros::dev)
+
+@PACKAGE_INIT@
+
+include(CMakeFindDependencyMacro)
+
+# Required dependencies for Ouroboros libraries
+find_dependency(Threads)
+
+include("${CMAKE_CURRENT_LIST_DIR}/OuroborosTargets.cmake")
+
+check_required_components(Ouroboros)
diff --git a/cmake/compiler.cmake b/cmake/compiler.cmake
index 6258cca0..5d452e02 100644
--- a/cmake/compiler.cmake
+++ b/cmake/compiler.cmake
@@ -31,42 +31,34 @@ test_and_set_c_compiler_flag_global(-Wdeclaration-after-statement)
test_and_set_c_compiler_flag_global(-Winfinite-recursion)
test_and_set_c_compiler_flag_global(-fmax-errors=5)
-set(DISABLE_COVERAGE ON CACHE BOOL "Disable code coverage analysis")
-
-if (NOT DISABLE_COVERAGE)
- test_and_set_c_compiler_flag_global(-g)
- test_and_set_c_compiler_flag_global(--coverage)
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage")
- set(ENABLE_COVERAGE ON)
-else()
- set(ENABLE_COVERAGE OFF)
-endif()
-
-if (NOT CMAKE_BUILD_TYPE)
+if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
"Build type (Release, Debug, DebugASan, DebugTSan, DebugLSan, DebugUSan, DebugAnalyzer)" FORCE)
endif()
-if (CMAKE_BUILD_TYPE STREQUAL "Release")
+if(CMAKE_BUILD_TYPE STREQUAL "Release")
test_and_set_c_compiler_flag_global(-O3)
-elseif (CMAKE_BUILD_TYPE STREQUAL "Debug")
+elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
test_and_set_c_compiler_flag_global(-g)
-elseif (CMAKE_BUILD_TYPE STREQUAL "DebugASan")
+elseif(CMAKE_BUILD_TYPE STREQUAL "DebugASan")
test_and_set_c_compiler_flag_global(-g)
test_and_set_c_compiler_flag_global(-fsanitize=address)
-elseif (CMAKE_BUILD_TYPE STREQUAL "DebugTSan")
+ add_link_options(-fsanitize=address)
+elseif(CMAKE_BUILD_TYPE STREQUAL "DebugTSan")
test_and_set_c_compiler_flag_global(-g)
test_and_set_c_compiler_flag_global(-fsanitize=thread)
-elseif (CMAKE_BUILD_TYPE STREQUAL "DebugLSan")
+ add_link_options(-fsanitize=thread)
+elseif(CMAKE_BUILD_TYPE STREQUAL "DebugLSan")
test_and_set_c_compiler_flag_global(-g)
test_and_set_c_compiler_flag_global(-fsanitize=leak)
-elseif (CMAKE_BUILD_TYPE STREQUAL "DebugUSan")
+ add_link_options(-fsanitize=leak)
+elseif(CMAKE_BUILD_TYPE STREQUAL "DebugUSan")
test_and_set_c_compiler_flag_global(-g)
test_and_set_c_compiler_flag_global(-fsanitize=undefined)
-elseif (CMAKE_BUILD_TYPE STREQUAL "DebugAnalyzer")
+ add_link_options(-fsanitize=undefined)
+elseif(CMAKE_BUILD_TYPE STREQUAL "DebugAnalyzer")
test_and_set_c_compiler_flag_global(-g)
test_and_set_c_compiler_flag_global(-fanalyzer)
-else ()
- message(FATAL_ERROR "Unkown build type ${CMAKE_BUILD_TYPE}")
-endif ()
+else()
+ message(FATAL_ERROR "Unknown build type ${CMAKE_BUILD_TYPE}")
+endif()
diff --git a/cmake/config/global.cmake b/cmake/config/global.cmake
new file mode 100644
index 00000000..243e1ba0
--- /dev/null
+++ b/cmake/config/global.cmake
@@ -0,0 +1,45 @@
+# Global configuration options for Ouroboros
+# These options affect the entire framework
+
+# Installation directories
+set(OUROBOROS_CONFIG_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}/ouroboros" CACHE PATH
+ "Configuration directory")
+
+# Security directories
+set(OUROBOROS_SECURITY_DIR "${OUROBOROS_CONFIG_DIR}/security" CACHE PATH
+ "Security directory holding authentication information")
+set(OUROBOROS_CA_CRT_DIR "${OUROBOROS_SECURITY_DIR}/cacert" CACHE PATH
+ "Directory holding trusted CA certificates")
+set(OUROBOROS_SRV_CRT_DIR "${OUROBOROS_SECURITY_DIR}/server" CACHE PATH
+ "Directory holding server certificates")
+set(OUROBOROS_CLI_CRT_DIR "${OUROBOROS_SECURITY_DIR}/client" CACHE PATH
+ "Directory holding client certificates")
+set(OUROBOROS_UNTRUSTED_DIR "${OUROBOROS_SECURITY_DIR}/untrusted" CACHE PATH
+ "Directory holding untrusted intermediate certificates")
+
+# Shared memory naming
+set(SHM_PREFIX "ouroboros" CACHE STRING
+ "String to prepend to POSIX shared memory filenames")
+set(SHM_LOCKFILE_NAME "/${SHM_PREFIX}.lockfile" CACHE INTERNAL
+ "Filename for the POSIX shared memory lockfile")
+
+# FUSE configuration
+if(HAVE_FUSE)
+ set(FUSE_PREFIX "/tmp/ouroboros" CACHE STRING
+ "Mountpoint for RIB filesystem")
+endif()
+
+# Secure memory configuration
+set(IRMD_SECMEM_MAX 1048576 CACHE STRING "IRMd secure heap size")
+set(PROC_SECMEM_MAX 1048576 CACHE STRING "Process secure heap size")
+set(SECMEM_GUARD 32 CACHE STRING "Secure heap min size")
+
+# Container/deployment options
+set(BUILD_CONTAINER FALSE CACHE BOOL
+ "Disable thread priority setting for container compatibility")
+set(DISABLE_CORE_LOCK TRUE CACHE BOOL
+ "Disable locking performance threads to a core")
+
+# IPC socket configuration
+set(SOCK_BUF_SIZE 10240 CACHE STRING
+ "Size of the buffer used by the UNIX sockets for local IPC")
diff --git a/cmake/config/ipcp/broadcast.cmake b/cmake/config/ipcp/broadcast.cmake
new file mode 100644
index 00000000..3c4d98da
--- /dev/null
+++ b/cmake/config/ipcp/broadcast.cmake
@@ -0,0 +1,4 @@
+# Broadcast IPCP configuration options for Ouroboros
+
+set(IPCP_BROADCAST_MPL 100 CACHE STRING
+ "Default maximum packet lifetime for the Broadcast IPCP, in ms")
diff --git a/cmake/config/ipcp/common.cmake b/cmake/config/ipcp/common.cmake
new file mode 100644
index 00000000..ffd5dc32
--- /dev/null
+++ b/cmake/config/ipcp/common.cmake
@@ -0,0 +1,43 @@
+# Common IPCP configuration options for Ouroboros
+# Options affecting all IPC Process types
+
+# Connection manager
+set(CONNMGR_RCV_TIMEOUT 1000 CACHE STRING
+ "Timeout for the connection manager to wait for OCEP info (ms).")
+
+# Debugging
+set(IPCP_DEBUG_LOCAL FALSE CACHE BOOL
+ "Use PID as address for local debugging")
+
+# QoS cube priorities (0-99, higher = more priority)
+set(IPCP_QOS_CUBE_BE_PRIO 50 CACHE STRING
+ "Priority for best effort QoS cube (0-99)")
+set(IPCP_QOS_CUBE_VIDEO_PRIO 90 CACHE STRING
+ "Priority for video QoS cube (0-99)")
+set(IPCP_QOS_CUBE_VOICE_PRIO 99 CACHE STRING
+ "Priority for voice QoS cube (0-99)")
+
+# Validate QoS cube priorities
+if((IPCP_QOS_CUBE_BE_PRIO LESS 0) OR (IPCP_QOS_CUBE_BE_PRIO GREATER 99))
+ message(FATAL_ERROR "Invalid priority for best effort QoS cube (must be 0-99)")
+endif()
+if((IPCP_QOS_CUBE_VIDEO_PRIO LESS 0) OR (IPCP_QOS_CUBE_VIDEO_PRIO GREATER 99))
+ message(FATAL_ERROR "Invalid priority for video QoS cube (must be 0-99)")
+endif()
+if((IPCP_QOS_CUBE_VOICE_PRIO LESS 0) OR (IPCP_QOS_CUBE_VOICE_PRIO GREATER 99))
+ message(FATAL_ERROR "Invalid priority for voice QoS cube (must be 0-99)")
+endif()
+
+# Threading
+set(IPCP_MIN_THREADS 4 CACHE STRING
+ "Minimum number of worker threads in the IPCP")
+set(IPCP_ADD_THREADS 4 CACHE STRING
+ "Number of extra threads to start when an IPCP faces thread starvation")
+set(IPCP_SCHED_THR_MUL 2 CACHE STRING
+ "Number of scheduler threads per QoS cube")
+
+# Linux-specific
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(IPCP_LINUX_TIMERSLACK_NS 100 CACHE STRING
+ "Slack value for high resolution timers on Linux systems.")
+endif()
diff --git a/cmake/config/ipcp/eth.cmake b/cmake/config/ipcp/eth.cmake
new file mode 100644
index 00000000..2f50d24d
--- /dev/null
+++ b/cmake/config/ipcp/eth.cmake
@@ -0,0 +1,15 @@
+# Ethernet IPCP configuration options for Ouroboros
+# Options for eth-llc and eth-dix IPCPs
+
+set(IPCP_ETH_RD_THR 1 CACHE STRING
+ "Number of reader threads in Ethernet IPCP")
+set(IPCP_ETH_WR_THR 1 CACHE STRING
+ "Number of writer threads in Ethernet IPCP")
+set(IPCP_ETH_QDISC_BYPASS false CACHE BOOL
+ "Bypass the Qdisc in the kernel when using raw sockets")
+set(IPCP_ETH_LO_MTU 9000 CACHE STRING
+ "Restrict Ethernet MTU over loopback interfaces")
+set(IPCP_ETH_MGMT_FRAME_SIZE 9000 CACHE STRING
+ "Management frame buffer size for Ethernet IPCPs")
+set(IPCP_ETH_MPL 100 CACHE STRING
+ "Default maximum packet lifetime for the Ethernet IPCPs, in ms")
diff --git a/cmake/config/ipcp/local.cmake b/cmake/config/ipcp/local.cmake
new file mode 100644
index 00000000..df47c45b
--- /dev/null
+++ b/cmake/config/ipcp/local.cmake
@@ -0,0 +1,7 @@
+# Local IPCP configuration options for Ouroboros
+
+set(IPCP_LOCAL_MPL 100 CACHE STRING
+ "Default maximum packet lifetime for the Local IPCP, in ms")
+
+set(IPCP_LOCAL_POLLING FALSE CACHE BOOL
+ "Enable active polling in the Local IPCP for low-latency mode")
diff --git a/cmake/config/ipcp/udp.cmake b/cmake/config/ipcp/udp.cmake
new file mode 100644
index 00000000..691948ab
--- /dev/null
+++ b/cmake/config/ipcp/udp.cmake
@@ -0,0 +1,9 @@
+# UDP IPCP configuration options for Ouroboros
+# Options for udp4 and udp6 IPCPs
+
+set(IPCP_UDP_RD_THR 3 CACHE STRING
+ "Number of reader threads in UDP IPCPs")
+set(IPCP_UDP_WR_THR 3 CACHE STRING
+ "Number of writer threads in UDP IPCPs")
+set(IPCP_UDP_MPL 5000 CACHE STRING
+ "Default maximum packet lifetime for the UDP IPCPs, in ms")
diff --git a/cmake/config/ipcp/unicast.cmake b/cmake/config/ipcp/unicast.cmake
new file mode 100644
index 00000000..905c661a
--- /dev/null
+++ b/cmake/config/ipcp/unicast.cmake
@@ -0,0 +1,12 @@
+# Unicast IPCP configuration options for Ouroboros
+
+set(IPCP_UNICAST_MPL 100 CACHE STRING
+ "Default maximum packet lifetime for the Unicast IPCP, in ms")
+set(PFT_SIZE 256 CACHE STRING
+ "Prefix forwarding table size for the Unicast IPCP")
+
+# Protocol debugging
+set(DEBUG_PROTO_DHT FALSE CACHE BOOL
+ "Add DHT protocol debug logging")
+set(DEBUG_PROTO_LS FALSE CACHE BOOL
+ "Add link state protocol debug logging")
diff --git a/cmake/config/irmd.cmake b/cmake/config/irmd.cmake
new file mode 100644
index 00000000..9795e4a4
--- /dev/null
+++ b/cmake/config/irmd.cmake
@@ -0,0 +1,36 @@
+# IRMd configuration options for Ouroboros
+# Options affecting the IPC Resource Manager daemon
+
+# Timeouts (all in milliseconds unless noted)
+set(IRMD_REQ_ARR_TIMEOUT 1000 CACHE STRING
+ "Timeout for an application to respond to a new flow (ms)")
+set(BOOTSTRAP_TIMEOUT 5000 CACHE STRING
+ "Timeout for an IPCP to bootstrap (ms)")
+set(ENROLL_TIMEOUT 20000 CACHE STRING
+ "Timeout for an IPCP to enroll (ms)")
+set(REG_TIMEOUT 20000 CACHE STRING
+ "Timeout for registering a name (ms)")
+set(QUERY_TIMEOUT 200 CACHE STRING
+ "Timeout to query a name with an IPCP (ms)")
+set(CONNECT_TIMEOUT 20000 CACHE STRING
+ "Timeout to connect an IPCP to another IPCP (ms)")
+set(FLOW_ALLOC_TIMEOUT 20000 CACHE STRING
+ "Timeout for a flow allocation response (ms)")
+
+# OAP (Ouroboros Authentication Protocol)
+set(OAP_REPLAY_TIMER 20 CACHE STRING
+ "OAP replay protection window (s)")
+set(DEBUG_PROTO_OAP FALSE CACHE BOOL
+ "Add Flow allocation protocol message output to IRMd debug logging")
+
+# Threading
+set(IRMD_MIN_THREADS 8 CACHE STRING
+ "Minimum number of worker threads in the IRMd")
+set(IRMD_ADD_THREADS 8 CACHE STRING
+ "Number of extra threads to start when the IRMD faces thread starvation")
+
+# Process management
+set(IRMD_PKILL_TIMEOUT 30 CACHE STRING
+ "Number of seconds to wait before sending SIGKILL to subprocesses on exit")
+set(IRMD_KILL_ALL_PROCESSES TRUE CACHE BOOL
+ "Kill all processes on exit")
diff --git a/cmake/lib/lib.cmake b/cmake/config/lib.cmake
index 86b4418c..287f30dc 100644
--- a/cmake/lib/lib.cmake
+++ b/cmake/config/lib.cmake
@@ -1,7 +1,7 @@
-set(LIB_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src/lib")
-set(LIB_BINARY_DIR "${CMAKE_BINARY_DIR}/src/lib")
+# Library configuration options for Ouroboros
+# Options affecting libouroboros-common, libouroboros-dev, libouroboros-irm
-# Library configuration variables
+# Flow limits
set(SYS_MAX_FLOWS 10240 CACHE STRING
"Maximum number of total flows for this system")
set(PROG_MAX_FLOWS 4096 CACHE STRING
@@ -11,29 +11,32 @@ set(PROG_RES_FDS 64 CACHE STRING
set(PROG_MAX_FQUEUES 32 CACHE STRING
"Maximum number of flow sets per application")
-if (NOT APPLE)
+# Threading
+if(NOT APPLE)
set(PTHREAD_COND_CLOCK "CLOCK_MONOTONIC" CACHE STRING
"Clock to use for condition variable timing")
-else ()
+else()
set(PTHREAD_COND_CLOCK "CLOCK_REALTIME" CACHE INTERNAL
"Clock to use for condition variable timing")
-endif ()
+endif()
+# Timeouts
set(SOCKET_TIMEOUT 500 CACHE STRING
"Default timeout for responses from IPCPs (ms)")
-set(SHM_PREFIX "ouroboros" CACHE STRING
- "String to prepend to POSIX shared memory filenames")
-set(SHM_LOCKFILE_NAME "/${SHM_PREFIX}.lockfile" CACHE INTERNAL
- "Filename for the POSIX shared memory lockfile")
+# QoS settings
set(QOS_DISABLE_CRC TRUE CACHE BOOL
"Ignores ber setting on all QoS cubes")
+
+# Delta-t protocol timers
set(DELTA_T_MPL 60 CACHE STRING
"Maximum packet lifetime (s)")
set(DELTA_T_ACK 10 CACHE STRING
"Maximum time to acknowledge a packet (s)")
set(DELTA_T_RTX 120 CACHE STRING
"Maximum time to retransmit a packet (s)")
+
+# FRCT configuration
set(FRCT_REORDER_QUEUE_SIZE 256 CACHE STRING
"Size of the reordering queue, must be a power of 2")
set(FRCT_START_WINDOW 64 CACHE STRING
@@ -48,6 +51,8 @@ set(FRCT_RTO_MIN 250 CACHE STRING
"Minimum Retransmission Timeout (RTO) for FRCT (us)")
set(FRCT_TICK_TIME 5000 CACHE STRING
"Tick time for FRCT activity (retransmission, acknowledgments) (us)")
+
+# Retransmission (RXM) configuration
set(RXM_BUFFER_ON_HEAP FALSE CACHE BOOL
"Store packets for retransmission on the heap instead of in packet buffer")
set(RXM_BLOCKING TRUE CACHE BOOL
@@ -60,23 +65,30 @@ set(RXM_WHEEL_LEVELS 3 CACHE STRING
"Number of levels in the retransmission wheel")
set(RXM_WHEEL_SLOTS_PER_LEVEL 256 CACHE STRING
"Number of slots per level in the retransmission wheel, must be a power of 2")
+
+# Acknowledgment wheel configuration
set(ACK_WHEEL_SLOTS 256 CACHE STRING
"Number of slots in the acknowledgment wheel, must be a power of 2")
set(ACK_WHEEL_RESOLUTION 18 CACHE STRING
"Minimum acknowledgment delay (ns), as a power to 2")
+
+# Thread pool manager (TPM) debugging
set(TPM_DEBUG_REPORT_INTERVAL 0 CACHE STRING
"Interval at wich the TPM will report long running threads (s), 0 disables")
set(TPM_DEBUG_ABORT_TIMEOUT 0 CACHE STRING
"TPM abort process after a thread reaches this timeout (s), 0 disables")
+
+# Encryption
set(KEY_ROTATION_BIT 20 CACHE STRING
"Bit position in packet counter that triggers key rotation (default 20 = every 2^20 packets)")
-if (HAVE_FUSE)
+# Flow statistics (requires FUSE)
+if(HAVE_FUSE)
set(PROC_FLOW_STATS TRUE CACHE BOOL
"Enable flow statistics tracking for application flows")
- if (PROC_FLOW_STATS)
- message(STATUS "Application flow statistics enabled")
- else ()
- message(STATUS "Application flow statistics disabled")
- endif ()
-endif ()
+ if(PROC_FLOW_STATS)
+ message(STATUS "Application flow statistics enabled")
+ else()
+ message(STATUS "Application flow statistics disabled")
+ endif()
+endif()
diff --git a/cmake/config/ssm.cmake b/cmake/config/ssm.cmake
new file mode 100644
index 00000000..c1f34655
--- /dev/null
+++ b/cmake/config/ssm.cmake
@@ -0,0 +1,131 @@
+# Secure Shared Memory (SSM) pool configuration for Ouroboros
+# This file defines the allocation parameters for the secure shared memory
+# pool allocator
+
+# Shared memory pool naming configuration
+set(SSM_PREFIX "ouroboros" CACHE STRING
+ "Prefix for secure shared memory pools")
+
+# Pool naming (internal)
+set(SSM_GSPP_NAME "/${SSM_PREFIX}.gspp" CACHE INTERNAL
+ "Name for the Global Shared Packet Pool")
+set(SSM_PUP_NAME_FMT "/${SSM_PREFIX}.pup.%d" CACHE INTERNAL
+ "Format string for Per-User Pool names (uid as argument)")
+
+# Packet buffer configuration
+set(SSM_POOL_NAME "/${SHM_PREFIX}.pool" CACHE INTERNAL
+ "Name for the main POSIX shared memory pool")
+set(SSM_POOL_BLOCKS 16384 CACHE STRING
+ "Number of blocks in SSM packet pool, must be a power of 2")
+set(SSM_PK_BUFF_HEADSPACE 256 CACHE STRING
+ "Bytes of headspace to reserve for future headers")
+set(SSM_PK_BUFF_TAILSPACE 32 CACHE STRING
+ "Bytes of tailspace to reserve for future tails")
+set(SSM_RBUFF_SIZE 1024 CACHE STRING
+ "Number of blocks in rbuff buffer, must be a power of 2")
+set(SSM_RBUFF_PREFIX "/${SHM_PREFIX}.rbuff." CACHE INTERNAL
+ "Prefix for rbuff POSIX shared memory filenames")
+set(SSM_FLOW_SET_PREFIX "/${SHM_PREFIX}.set." CACHE INTERNAL
+ "Prefix for the POSIX shared memory flow set")
+
+# Number of shards per size class for reducing contention
+set(SSM_POOL_SHARDS 4 CACHE STRING
+ "Number of allocator shards per size class")
+
+# Global Shared Packet Pool (GSPP) - for privileged processes
+# Shared by all processes in 'ouroboros' group (~60 MB total)
+set(SSM_GSPP_256_BLOCKS 1024 CACHE STRING
+ "GSPP: Number of 256B blocks")
+set(SSM_GSPP_512_BLOCKS 768 CACHE STRING
+ "GSPP: Number of 512B blocks")
+set(SSM_GSPP_1K_BLOCKS 512 CACHE STRING
+ "GSPP: Number of 1KB blocks")
+set(SSM_GSPP_2K_BLOCKS 384 CACHE STRING
+ "GSPP: Number of 2KB blocks")
+set(SSM_GSPP_4K_BLOCKS 256 CACHE STRING
+ "GSPP: Number of 4KB blocks")
+set(SSM_GSPP_16K_BLOCKS 128 CACHE STRING
+ "GSPP: Number of 16KB blocks")
+set(SSM_GSPP_64K_BLOCKS 64 CACHE STRING
+ "GSPP: Number of 64KB blocks")
+set(SSM_GSPP_256K_BLOCKS 32 CACHE STRING
+ "GSPP: Number of 256KB blocks")
+set(SSM_GSPP_1M_BLOCKS 16 CACHE STRING
+ "GSPP: Number of 1MB blocks")
+
+# Per-User Pool (PUP) - for unprivileged applications
+# Each unprivileged app gets its own smaller pool (~7.5 MB total)
+set(SSM_PUP_256_BLOCKS 128 CACHE STRING
+ "PUP: Number of 256B blocks")
+set(SSM_PUP_512_BLOCKS 96 CACHE STRING
+ "PUP: Number of 512B blocks")
+set(SSM_PUP_1K_BLOCKS 64 CACHE STRING
+ "PUP: Number of 1KB blocks")
+set(SSM_PUP_2K_BLOCKS 48 CACHE STRING
+ "PUP: Number of 2KB blocks")
+set(SSM_PUP_4K_BLOCKS 32 CACHE STRING
+ "PUP: Number of 4KB blocks")
+set(SSM_PUP_16K_BLOCKS 16 CACHE STRING
+ "PUP: Number of 16KB blocks")
+set(SSM_PUP_64K_BLOCKS 8 CACHE STRING
+ "PUP: Number of 64KB blocks")
+set(SSM_PUP_256K_BLOCKS 2 CACHE STRING
+ "PUP: Number of 256KB blocks")
+set(SSM_PUP_1M_BLOCKS 0 CACHE STRING
+ "PUP: Number of 1MB blocks")
+
+# SSM pool size calculations
+include(utils/HumanReadable)
+
+math(EXPR SSM_GSPP_TOTAL_SIZE
+ "(1 << 8) * ${SSM_GSPP_256_BLOCKS} + \
+ (1 << 9) * ${SSM_GSPP_512_BLOCKS} + \
+ (1 << 10) * ${SSM_GSPP_1K_BLOCKS} + \
+ (1 << 11) * ${SSM_GSPP_2K_BLOCKS} + \
+ (1 << 12) * ${SSM_GSPP_4K_BLOCKS} + \
+ (1 << 14) * ${SSM_GSPP_16K_BLOCKS} + \
+ (1 << 16) * ${SSM_GSPP_64K_BLOCKS} + \
+ (1 << 18) * ${SSM_GSPP_256K_BLOCKS} + \
+ (1 << 20) * ${SSM_GSPP_1M_BLOCKS}")
+
+set(SSM_GSPP_TOTAL_SIZE ${SSM_GSPP_TOTAL_SIZE} CACHE INTERNAL
+ "GSPP total size in bytes")
+
+math(EXPR SSM_PUP_TOTAL_SIZE
+ "(1 << 8) * ${SSM_PUP_256_BLOCKS} + \
+ (1 << 9) * ${SSM_PUP_512_BLOCKS} + \
+ (1 << 10) * ${SSM_PUP_1K_BLOCKS} + \
+ (1 << 11) * ${SSM_PUP_2K_BLOCKS} + \
+ (1 << 12) * ${SSM_PUP_4K_BLOCKS} + \
+ (1 << 14) * ${SSM_PUP_16K_BLOCKS} + \
+ (1 << 16) * ${SSM_PUP_64K_BLOCKS} + \
+ (1 << 18) * ${SSM_PUP_256K_BLOCKS} + \
+ (1 << 20) * ${SSM_PUP_1M_BLOCKS}")
+
+set(SSM_PUP_TOTAL_SIZE ${SSM_PUP_TOTAL_SIZE} CACHE INTERNAL
+ "PUP total size in bytes")
+
+set(SSM_POOL_TOTAL_SIZE ${SSM_GSPP_TOTAL_SIZE} CACHE INTERNAL
+ "Total shared memory pool size in bytes")
+
+format_bytes_human_readable(${SSM_GSPP_TOTAL_SIZE} SSM_GSPP_SIZE_DISPLAY)
+format_bytes_human_readable(${SSM_PUP_TOTAL_SIZE} SSM_PUP_SIZE_DISPLAY)
+
+message(STATUS "Secure Shared Memory Pool Configuration:")
+message(STATUS " Pool prefix: ${SSM_PREFIX}")
+message(STATUS " Size classes: "
+ "256B, 512B, 1KiB, 2KiB, 4KiB, 16KiB, 64KiB, 256KiB, 1MiB")
+message(STATUS " Max allocation: 1 MB")
+message(STATUS " Shards per class: ${SSM_POOL_SHARDS}")
+message(STATUS " GSPP (privileged): ${SSM_GSPP_SIZE_DISPLAY} "
+ "(${SSM_GSPP_TOTAL_SIZE} bytes)")
+message(STATUS " Blocks: ${SSM_GSPP_256_BLOCKS}, ${SSM_GSPP_512_BLOCKS}, "
+ "${SSM_GSPP_1K_BLOCKS}, ${SSM_GSPP_2K_BLOCKS}, ${SSM_GSPP_4K_BLOCKS}, "
+ "${SSM_GSPP_16K_BLOCKS}, ${SSM_GSPP_64K_BLOCKS}, ${SSM_GSPP_256K_BLOCKS}, "
+ "${SSM_GSPP_1M_BLOCKS}")
+message(STATUS " PUP (unprivileged): ${SSM_PUP_SIZE_DISPLAY} "
+ "(${SSM_PUP_TOTAL_SIZE} bytes)")
+message(STATUS " Blocks: ${SSM_PUP_256_BLOCKS}, ${SSM_PUP_512_BLOCKS}, "
+ "${SSM_PUP_1K_BLOCKS}, ${SSM_PUP_2K_BLOCKS}, ${SSM_PUP_4K_BLOCKS}, "
+ "${SSM_PUP_16K_BLOCKS}, ${SSM_PUP_64K_BLOCKS}, ${SSM_PUP_256K_BLOCKS}, "
+ "${SSM_PUP_1M_BLOCKS}")
diff --git a/cmake/config/tests.cmake b/cmake/config/tests.cmake
new file mode 100644
index 00000000..24730989
--- /dev/null
+++ b/cmake/config/tests.cmake
@@ -0,0 +1,17 @@
+# Test configuration options
+
+set(DISABLE_TESTS_LOGGING TRUE CACHE BOOL
+ "Disable Ouroboros log output in tests")
+if(DISABLE_TESTS_LOGGING)
+ message(STATUS "Ouroboros logging in test output disabled")
+else()
+ message(STATUS "Ouroboros logging in test output enabled")
+endif()
+
+set(DISABLE_TESTS_CORE_DUMPS TRUE CACHE BOOL
+ "Enable core dumps for tests (useful for debugging)")
+if(DISABLE_TESTS_CORE_DUMPS)
+ message(STATUS "Core dumps in tests enabled")
+else()
+ message(STATUS "Core dumps in tests disabled")
+endif()
diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake
index 4c999250..109fe1d6 100644
--- a/cmake/dependencies.cmake
+++ b/cmake/dependencies.cmake
@@ -1,19 +1,43 @@
-include(FindPkgConfig)
+find_package(PkgConfig QUIET)
include(CheckSymbolExists)
-include(dependencies/protobufc)
-include(dependencies/explicit_bzero)
-include(dependencies/systemlibraries)
-include(dependencies/robustmutex)
-include(dependencies/fuse)
-include(dependencies/libgcrypt)
-include(dependencies/openssl)
-include(dependencies/sysrandom)
-include(dependencies/libtoml)
-include(dependencies/rawsockets)
-include(dependencies/bpf)
-include(dependencies/netmap)
-include(dependencies/gcov)
-include(dependencies/lcov)
+# System libraries and features
+include(dependencies/system/protobufc)
+include(dependencies/system/libraries)
+include(dependencies/system/explicit_bzero)
+include(dependencies/system/robustmutex)
+include(dependencies/system/fuse)
+include(dependencies/system/sysrandom)
+
+# Cryptography
+include(dependencies/crypt/openssl)
+include(dependencies/crypt/libgcrypt)
+
+# IRMd
+include(dependencies/irmd/libtoml)
+
+# Ethernet IPCP backends
+include(dependencies/eth/rawsockets)
+include(dependencies/eth/bpf)
+include(dependencies/eth/netmap)
+if(HAVE_RAW_SOCKETS OR HAVE_BPF OR HAVE_NETMAP)
+ set(HAVE_ETH TRUE CACHE INTERNAL "Ethernet IPCP support available")
+else()
+ unset(HAVE_ETH CACHE)
+endif()
+
+# UDP IPCP
+include(dependencies/udp/ddns)
+
+# Coverage tools
+include(dependencies/coverage/gcov)
+include(dependencies/coverage/lcov)
+
+# Validate that at least one secure random generator is available
+if(NOT ((CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") OR APPLE OR
+ HAVE_SYS_RANDOM OR HAVE_OPENSSL_RNG OR HAVE_LIBGCRYPT))
+ message(FATAL_ERROR "No secure random generator found, "
+ "please install libgcrypt (> 1.7.0) or OpenSSL")
+endif()
diff --git a/cmake/dependencies/coverage/gcov.cmake b/cmake/dependencies/coverage/gcov.cmake
new file mode 100644
index 00000000..1b593155
--- /dev/null
+++ b/cmake/dependencies/coverage/gcov.cmake
@@ -0,0 +1,21 @@
+include(utils/CompilerUtils)
+
+find_program(GCOV_PATH gcov)
+
+if(GCOV_PATH)
+ set(HAVE_GCOV TRUE CACHE INTERNAL "gcov coverage tool available")
+ set(DISABLE_COVERAGE ON CACHE BOOL "Disable code coverage analysis")
+ if(DISABLE_COVERAGE)
+ message(STATUS "gcov found - coverage analysis available (disabled by user)")
+ else()
+ message(STATUS "Code coverage analysis enabled")
+ test_and_set_c_compiler_flag_global(-g)
+ test_and_set_c_compiler_flag_global(--coverage)
+ add_link_options(--coverage)
+ endif()
+else()
+ set(HAVE_GCOV FALSE CACHE INTERNAL "gcov coverage tool available")
+ message(STATUS "gcov not found - coverage analysis not available")
+endif()
+
+mark_as_advanced(GCOV_PATH)
diff --git a/cmake/dependencies/lcov.cmake b/cmake/dependencies/coverage/lcov.cmake
index db559332..65ed316e 100644
--- a/cmake/dependencies/lcov.cmake
+++ b/cmake/dependencies/coverage/lcov.cmake
@@ -1,17 +1,17 @@
find_program(LCOV_PATH lcov)
find_program(GENHTML_PATH genhtml)
-if (LCOV_PATH AND GENHTML_PATH)
- set(HAVE_LCOV TRUE CACHE INTERNAL "")
+if(LCOV_PATH AND GENHTML_PATH)
+ set(HAVE_LCOV TRUE CACHE INTERNAL "lcov HTML coverage reports available")
message(STATUS "lcov and genhtml found - HTML coverage reports available")
-else ()
- set(HAVE_LCOV FALSE CACHE INTERNAL "")
- if (NOT LCOV_PATH)
+else()
+ set(HAVE_LCOV FALSE CACHE INTERNAL "lcov HTML coverage reports available")
+ if(NOT LCOV_PATH)
message(STATUS "lcov not found - HTML coverage reports not available")
- endif ()
- if (NOT GENHTML_PATH)
+ endif()
+ if(NOT GENHTML_PATH)
message(STATUS "genhtml not found - HTML coverage reports not available")
- endif ()
-endif ()
+ endif()
+endif()
mark_as_advanced(LCOV_PATH GENHTML_PATH)
diff --git a/cmake/dependencies/crypt/libgcrypt.cmake b/cmake/dependencies/crypt/libgcrypt.cmake
new file mode 100644
index 00000000..4f8a4cfe
--- /dev/null
+++ b/cmake/dependencies/crypt/libgcrypt.cmake
@@ -0,0 +1,55 @@
+# Try pkg-config first, fall back to find_library
+if(PkgConfig_FOUND)
+ pkg_check_modules(LIBGCRYPT QUIET IMPORTED_TARGET libgcrypt>=1.7.0)
+ if(LIBGCRYPT_FOUND AND NOT TARGET Gcrypt::Gcrypt)
+ add_library(Gcrypt::Gcrypt ALIAS PkgConfig::LIBGCRYPT)
+ endif()
+endif()
+
+if(NOT LIBGCRYPT_FOUND)
+ find_library(LIBGCRYPT_LIBRARIES gcrypt QUIET)
+ if(LIBGCRYPT_LIBRARIES)
+ find_path(LIBGCRYPT_INCLUDE_DIR gcrypt.h
+ HINTS /usr/include /usr/local/include)
+ if(LIBGCRYPT_INCLUDE_DIR)
+ file(STRINGS ${LIBGCRYPT_INCLUDE_DIR}/gcrypt.h GCSTR
+ REGEX "^#define GCRYPT_VERSION ")
+ string(REGEX REPLACE "^#define GCRYPT_VERSION \"(.*)\".*$" "\\1"
+ LIBGCRYPT_VERSION "${GCSTR}")
+ if(NOT LIBGCRYPT_VERSION VERSION_LESS "1.7.0")
+ set(LIBGCRYPT_FOUND TRUE)
+ if(NOT TARGET Gcrypt::Gcrypt)
+ add_library(Gcrypt::Gcrypt UNKNOWN IMPORTED)
+ set_target_properties(Gcrypt::Gcrypt PROPERTIES
+ IMPORTED_LOCATION "${LIBGCRYPT_LIBRARIES}"
+ INTERFACE_INCLUDE_DIRECTORIES "${LIBGCRYPT_INCLUDE_DIR}")
+ endif()
+ endif()
+ endif()
+ endif()
+endif()
+
+if(LIBGCRYPT_FOUND)
+ set(DISABLE_LIBGCRYPT FALSE CACHE BOOL "Disable libgcrypt support")
+ if(NOT DISABLE_LIBGCRYPT)
+ if(LIBGCRYPT_VERSION)
+ message(STATUS "libgcrypt support enabled (version ${LIBGCRYPT_VERSION})")
+ else()
+ message(STATUS "libgcrypt support enabled")
+ endif()
+ set(HAVE_LIBGCRYPT TRUE CACHE INTERNAL "libgcrypt cryptography support available")
+ else()
+ message(STATUS "libgcrypt support disabled by user")
+ unset(HAVE_LIBGCRYPT CACHE)
+ endif()
+else()
+ message(STATUS "Install libgcrypt >= 1.7.0 to enable libgcrypt support")
+ unset(HAVE_LIBGCRYPT CACHE)
+endif()
+
+if(NOT HAVE_LIBGCRYPT)
+ set(LIBGCRYPT_LIBRARIES "")
+ set(LIBGCRYPT_INCLUDE_DIR "")
+endif()
+
+mark_as_advanced(LIBGCRYPT_LIBRARIES LIBGCRYPT_INCLUDE_DIR)
diff --git a/cmake/dependencies/openssl.cmake b/cmake/dependencies/crypt/openssl.cmake
index b02d64b4..ed07cc9d 100644
--- a/cmake/dependencies/openssl.cmake
+++ b/cmake/dependencies/crypt/openssl.cmake
@@ -1,18 +1,18 @@
find_package(OpenSSL QUIET)
-if (OPENSSL_FOUND)
+if(OPENSSL_FOUND)
set(HAVE_OPENSSL_RNG TRUE)
- if (OPENSSL_VERSION VERSION_LESS "3.0.0")
+ if(OPENSSL_VERSION VERSION_LESS "3.0.0")
message(STATUS "Install version >= 3.0.0 to enable OpenSSL support "
"(found version \"${OPENSSL_VERSION}\")")
- else ()
+ else()
set(DISABLE_OPENSSL FALSE CACHE BOOL "Disable OpenSSL support")
- if (NOT DISABLE_OPENSSL)
+ if(NOT DISABLE_OPENSSL)
message(STATUS "OpenSSL support enabled, found version ${OPENSSL_VERSION}")
- set(HAVE_OPENSSL TRUE CACHE INTERNAL "")
+ set(HAVE_OPENSSL TRUE CACHE INTERNAL "OpenSSL cryptography support available")
set(DISABLE_PQC FALSE CACHE BOOL "Disable post-quantum cryptography support")
- if (OPENSSL_VERSION VERSION_GREATER_EQUAL "3.4.0")
- if (NOT DISABLE_PQC)
- set(HAVE_OPENSSL_PQC TRUE CACHE INTERNAL "")
+ if(OPENSSL_VERSION VERSION_GREATER_EQUAL "3.4.0")
+ if(NOT DISABLE_PQC)
+ set(HAVE_OPENSSL_PQC TRUE CACHE INTERNAL "OpenSSL post-quantum cryptography available")
message(STATUS "OpenSSL PQC support enabled")
else()
message(STATUS "OpenSSL PQC support disabled by user")
@@ -25,18 +25,11 @@ if (OPENSSL_FOUND)
message(STATUS "OpenSSL support disabled")
unset(HAVE_OPENSSL CACHE)
endif()
- endif ()
+ endif()
else()
message(STATUS "Install OpenSSL version >= 3.0.0 to enable OpenSSL support")
unset(HAVE_OPENSSL_RNG)
unset(HAVE_OPENSSL CACHE)
- set(OPENSSL_INCLUDE_DIR "")
- set(OPENSSL_LIBRARIES "")
- set(OPENSSL_CRYPTO_LIBRARY "")
-endif ()
+endif()
-set(IRMD_SECMEM_MAX 1048576 CACHE STRING "IRMd secure heap size")
-set(PROC_SECMEM_MAX 1048576 CACHE STRING "Process secure heap size")
-set(SECMEM_GUARD 32 CACHE STRING "Secure heap min size")
-
-mark_as_advanced(OPENSSL_LIBRARIES OPENSSL_CRYPTO_LIBRARY)
+# Secure memory options are in cmake/config/global.cmake
diff --git a/cmake/dependencies/bpf.cmake b/cmake/dependencies/eth/bpf.cmake
index 8c04937f..c2f69e79 100644
--- a/cmake/dependencies/bpf.cmake
+++ b/cmake/dependencies/eth/bpf.cmake
@@ -1,20 +1,20 @@
# Berkeley Packet Filter support (BSD/macOS only)
-if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
+if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
find_path(BPF_C_INCLUDE_DIR
net/bpf.h
HINTS /usr/include /usr/local/include)
mark_as_advanced(BPF_C_INCLUDE_DIR)
- if (BPF_C_INCLUDE_DIR)
+ if(BPF_C_INCLUDE_DIR)
set(DISABLE_BPF FALSE CACHE BOOL
"Disable Berkeley Packet Filter support for Ethernet IPCPs")
- if (NOT DISABLE_BPF)
+ if(NOT DISABLE_BPF)
message(STATUS "Berkeley Packet Filter support for Ethernet IPCPs enabled")
set(HAVE_BPF TRUE)
- else ()
+ else()
message(STATUS "Berkeley Packet Filter support for Ethernet IPCPs disabled by user")
unset(HAVE_BPF)
- endif ()
- endif ()
-endif ()
+ endif()
+ endif()
+endif()
diff --git a/cmake/dependencies/netmap.cmake b/cmake/dependencies/eth/netmap.cmake
index d8d3781b..94ecd634 100644
--- a/cmake/dependencies/netmap.cmake
+++ b/cmake/dependencies/eth/netmap.cmake
@@ -5,14 +5,14 @@ find_path(NETMAP_C_INCLUDE_DIR
mark_as_advanced(NETMAP_C_INCLUDE_DIR)
-if (NOT HAVE_RAW_SOCKETS AND NOT HAVE_BPF AND NETMAP_C_INCLUDE_DIR)
+if(NOT HAVE_RAW_SOCKETS AND NOT HAVE_BPF AND NETMAP_C_INCLUDE_DIR)
set(DISABLE_NETMAP FALSE CACHE BOOL
"Disable netmap support for ETH IPCPs")
- if (NOT DISABLE_NETMAP)
+ if(NOT DISABLE_NETMAP)
message(STATUS "Netmap support for Ethernet IPCPs enabled")
set(HAVE_NETMAP TRUE)
- else ()
+ else()
message(STATUS "Netmap support for Ethernet IPCPs disabled by user")
unset(HAVE_NETMAP)
- endif ()
-endif ()
+ endif()
+endif()
diff --git a/cmake/dependencies/rawsockets.cmake b/cmake/dependencies/eth/rawsockets.cmake
index 92f7b8b7..395d9efb 100644
--- a/cmake/dependencies/rawsockets.cmake
+++ b/cmake/dependencies/eth/rawsockets.cmake
@@ -1,12 +1,12 @@
# Raw sockets support (Linux only)
-if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(DISABLE_RAW_SOCKETS FALSE CACHE BOOL
"Disable raw socket support for Ethernet IPCPs")
- if (NOT DISABLE_RAW_SOCKETS)
+ if(NOT DISABLE_RAW_SOCKETS)
message(STATUS "Raw socket support for Ethernet IPCPs enabled")
set(HAVE_RAW_SOCKETS TRUE)
- else ()
+ else()
message(STATUS "Raw socket support for Ethernet IPCPs disabled by user")
unset(HAVE_RAW_SOCKETS)
- endif ()
-endif ()
+ endif()
+endif()
diff --git a/cmake/dependencies/explicit_bzero.cmake b/cmake/dependencies/explicit_bzero.cmake
deleted file mode 100644
index 54a11d21..00000000
--- a/cmake/dependencies/explicit_bzero.cmake
+++ /dev/null
@@ -1 +0,0 @@
-check_symbol_exists(explicit_bzero "string.h" HAVE_EXPLICIT_BZERO) \ No newline at end of file
diff --git a/cmake/dependencies/fuse.cmake b/cmake/dependencies/fuse.cmake
deleted file mode 100644
index 8ef60292..00000000
--- a/cmake/dependencies/fuse.cmake
+++ /dev/null
@@ -1,23 +0,0 @@
-find_library(FUSE_LIBRARIES fuse QUIET)
-if (FUSE_LIBRARIES)
- #FIXME: Check for version >= 2.6
- set(DISABLE_FUSE FALSE CACHE BOOL "Disable FUSE support")
- if (NOT DISABLE_FUSE)
- message(STATUS "FUSE support enabled")
- set(FUSE_PREFIX "/tmp/ouroboros" CACHE STRING
- "Mountpoint for RIB filesystem")
- set(HAVE_FUSE TRUE CACHE INTERNAL "")
- else ()
- message(STATUS "FUSE support disabled by user")
- unset(HAVE_FUSE CACHE)
- endif ()
-else ()
- message(STATUS "Install FUSE version > 2.6 to enable RIB access")
-endif ()
-
-if (NOT HAVE_FUSE)
- set(FUSE_LIBRARIES "")
- set(FUSE_INCLUDE_DIR "")
-endif ()
-
-mark_as_advanced(FUSE_LIBRARIES)
diff --git a/cmake/dependencies/gcov.cmake b/cmake/dependencies/gcov.cmake
deleted file mode 100644
index c4d1caf0..00000000
--- a/cmake/dependencies/gcov.cmake
+++ /dev/null
@@ -1,11 +0,0 @@
-find_program(GCOV_PATH gcov)
-
-if (GCOV_PATH)
- set(HAVE_GCOV TRUE CACHE INTERNAL "")
- message(STATUS "gcov found - coverage analysis available")
-else ()
- set(HAVE_GCOV FALSE CACHE INTERNAL "")
- message(STATUS "gcov not found - coverage analysis not available")
-endif ()
-
-mark_as_advanced(GCOV_PATH)
diff --git a/cmake/dependencies/irmd/libtoml.cmake b/cmake/dependencies/irmd/libtoml.cmake
new file mode 100644
index 00000000..dcbc17e4
--- /dev/null
+++ b/cmake/dependencies/irmd/libtoml.cmake
@@ -0,0 +1,29 @@
+find_library(LIBTOML_LIBRARY toml QUIET)
+if(LIBTOML_LIBRARY)
+ find_path(LIBTOML_INCLUDE_DIR toml.h)
+ set(DISABLE_CONFIGFILE FALSE CACHE BOOL
+ "Disable configuration file support")
+ if(NOT DISABLE_CONFIGFILE)
+ set(OUROBOROS_CONFIG_FILE irmd.conf CACHE STRING
+ "Name of the IRMd configuration file")
+ set(HAVE_TOML TRUE CACHE INTERNAL "TOML configuration file support available")
+ message(STATUS "Configuration file support enabled")
+ message(STATUS "Configuration directory: ${OUROBOROS_CONFIG_DIR}")
+ # Create imported target for consistency with other dependencies
+ if(NOT TARGET toml::toml)
+ add_library(toml::toml UNKNOWN IMPORTED)
+ set_target_properties(toml::toml PROPERTIES
+ IMPORTED_LOCATION "${LIBTOML_LIBRARY}"
+ INTERFACE_INCLUDE_DIRECTORIES "${LIBTOML_INCLUDE_DIR}")
+ endif()
+ else()
+ message(STATUS "Configuration file support disabled by user")
+ unset(OUROBOROS_CONFIG_FILE CACHE)
+ unset(HAVE_TOML CACHE)
+ endif()
+ mark_as_advanced(LIBTOML_LIBRARY LIBTOML_INCLUDE_DIR)
+else()
+ message(STATUS "Install tomlc99 for config file support")
+ message(STATUS " https://github.com/cktan/tomlc99")
+ unset(HAVE_TOML CACHE)
+endif()
diff --git a/cmake/dependencies/libgcrypt.cmake b/cmake/dependencies/libgcrypt.cmake
deleted file mode 100644
index 90a25f36..00000000
--- a/cmake/dependencies/libgcrypt.cmake
+++ /dev/null
@@ -1,31 +0,0 @@
-find_library(LIBGCRYPT_LIBRARIES gcrypt QUIET)
-if (LIBGCRYPT_LIBRARIES)
- find_path(LIBGCRYPT_INCLUDE_DIR gcrypt.h
- HINTS /usr/include /usr/local/include)
- if (LIBGCRYPT_INCLUDE_DIR)
- file(STRINGS ${LIBGCRYPT_INCLUDE_DIR}/gcrypt.h GCSTR
- REGEX "^#define GCRYPT_VERSION ")
- string(REGEX REPLACE "^#define GCRYPT_VERSION \"(.*)\".*$" "\\1"
- GCVER "${GCSTR}")
- if (NOT GCVER VERSION_LESS "1.7.0")
- set(DISABLE_LIBGCRYPT FALSE CACHE BOOL "Disable libgcrypt support")
- if (NOT DISABLE_LIBGCRYPT)
- message(STATUS "libgcrypt support enabled")
- set(HAVE_LIBGCRYPT TRUE CACHE INTERNAL "")
- else ()
- message(STATUS "libgcrypt support disabled by user")
- unset(HAVE_LIBGCRYPT CACHE)
- endif()
- else ()
- message(STATUS "Install version >= \"1.7.0\" to enable libgcrypt support "
- "(found version \"${GCVER}\")")
- endif()
- endif ()
-endif ()
-
-if (NOT HAVE_LIBGCRYPT)
- set(LIBGCRYPT_LIBRARIES "")
- set(LIBGCRYPT_INCLUDE_DIR "")
-endif ()
-
-mark_as_advanced(LIBGCRYPT_LIBRARIES LIBGCRYPT_INCLUDE_DIR)
diff --git a/cmake/dependencies/libtoml.cmake b/cmake/dependencies/libtoml.cmake
deleted file mode 100644
index 3974a1dd..00000000
--- a/cmake/dependencies/libtoml.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-find_library(LIBTOML_LIBRARIES toml QUIET)
-if (LIBTOML_LIBRARIES)
- find_path(LIBTOML_INCLUDE toml.h)
- mark_as_advanced(LIBTOML_LIBRARIES LIBTOML_INCLUDE)
-endif ()
diff --git a/cmake/dependencies/sysrandom.cmake b/cmake/dependencies/sysrandom.cmake
deleted file mode 100644
index 972db801..00000000
--- a/cmake/dependencies/sysrandom.cmake
+++ /dev/null
@@ -1,21 +0,0 @@
-if (APPLE OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
- set(SYS_RND_HDR "")
-else ()
- find_path(SYS_RND_HDR sys/random.h PATH /usr/include/ /usr/local/include/)
- if (SYS_RND_HDR)
- message(STATUS "Found sys/random.h in ${SYS_RND_HDR}")
- set(HAVE_SYS_RANDOM TRUE)
- else ()
- set(SYS_RND_HDR "")
- unset(HAVE_SYS_RANDOM)
- endif ()
-endif()
-
-# Validate that at least one secure random generator is available
-if (NOT ((CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") OR APPLE OR
- HAVE_SYS_RANDOM OR HAVE_OPENSSL_RNG OR HAVE_LIBGCRYPT))
- message(FATAL_ERROR "No secure random generator found, "
- "please install libgcrypt (> 1.7.0) or OpenSSL")
-endif ()
-
-mark_as_advanced(SYS_RND_HDR)
diff --git a/cmake/dependencies/system/explicit_bzero.cmake b/cmake/dependencies/system/explicit_bzero.cmake
new file mode 100644
index 00000000..89ab3abc
--- /dev/null
+++ b/cmake/dependencies/system/explicit_bzero.cmake
@@ -0,0 +1,4 @@
+# Check for explicit_bzero in string.h
+# glibc requires _DEFAULT_SOURCE to expose it; harmless on other platforms
+list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_DEFAULT_SOURCE)
+check_symbol_exists(explicit_bzero "string.h" HAVE_EXPLICIT_BZERO)
diff --git a/cmake/dependencies/system/fuse.cmake b/cmake/dependencies/system/fuse.cmake
new file mode 100644
index 00000000..7de12b31
--- /dev/null
+++ b/cmake/dependencies/system/fuse.cmake
@@ -0,0 +1,44 @@
+# Try pkg-config first, fall back to find_library
+if(PkgConfig_FOUND)
+ pkg_check_modules(FUSE QUIET IMPORTED_TARGET fuse>=2.6)
+ if(FUSE_FOUND AND NOT TARGET Fuse::Fuse)
+ add_library(Fuse::Fuse ALIAS PkgConfig::FUSE)
+ endif()
+endif()
+
+if(NOT FUSE_FOUND)
+ find_library(FUSE_LIBRARIES fuse QUIET)
+ if(FUSE_LIBRARIES)
+ set(FUSE_FOUND TRUE)
+ if(NOT TARGET Fuse::Fuse)
+ add_library(Fuse::Fuse UNKNOWN IMPORTED)
+ set_target_properties(Fuse::Fuse PROPERTIES
+ IMPORTED_LOCATION "${FUSE_LIBRARIES}")
+ endif()
+ endif()
+endif()
+
+if(FUSE_FOUND)
+ set(DISABLE_FUSE FALSE CACHE BOOL "Disable FUSE support")
+ if(NOT DISABLE_FUSE)
+ if(FUSE_VERSION)
+ message(STATUS "FUSE support enabled (version ${FUSE_VERSION})")
+ else()
+ message(STATUS "FUSE support enabled")
+ endif()
+ # FUSE_PREFIX is set in cmake/config/global.cmake
+ set(HAVE_FUSE TRUE CACHE INTERNAL "FUSE filesystem support available")
+ else()
+ message(STATUS "FUSE support disabled by user")
+ unset(HAVE_FUSE CACHE)
+ endif()
+else()
+ message(STATUS "Install FUSE version >= 2.6 to enable RIB access")
+ unset(HAVE_FUSE CACHE)
+endif()
+
+if(NOT HAVE_FUSE)
+ set(FUSE_LIBRARIES "")
+endif()
+
+mark_as_advanced(FUSE_LIBRARIES)
diff --git a/cmake/dependencies/system/libraries.cmake b/cmake/dependencies/system/libraries.cmake
new file mode 100644
index 00000000..55c22d6a
--- /dev/null
+++ b/cmake/dependencies/system/libraries.cmake
@@ -0,0 +1,17 @@
+if(NOT APPLE)
+ find_library(LIBRT_LIBRARIES rt)
+ mark_as_advanced(LIBRT_LIBRARIES)
+ if(NOT LIBRT_LIBRARIES)
+ message(FATAL_ERROR "Could not find librt")
+ endif()
+else()
+ set(LIBRT_LIBRARIES "")
+endif()
+
+find_package(Threads REQUIRED)
+
+find_library(LIBM_LIBRARIES m)
+mark_as_advanced(LIBM_LIBRARIES)
+if(NOT LIBM_LIBRARIES)
+ message(FATAL_ERROR "Could not find libm")
+endif()
diff --git a/cmake/dependencies/protobufc.cmake b/cmake/dependencies/system/protobufc.cmake
index f1fab59d..b7e0062a 100644
--- a/cmake/dependencies/protobufc.cmake
+++ b/cmake/dependencies/system/protobufc.cmake
@@ -1,11 +1,13 @@
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/utils")
find_package(ProtobufC QUIET)
-if (NOT (PROTOBUF_C_INCLUDE_DIRS AND PROTOBUF_C_LIBRARY
+if(NOT (PROTOBUF_C_INCLUDE_DIRS AND PROTOBUF_C_LIBRARY
AND PROTOBUF_PROTOC_C_EXECUTABLE))
message(FATAL_ERROR "Protobuf C compiler required but not found. "
"Please install Google Protocol Buffers.")
-else ()
+else()
message(STATUS "Found protobuf C compiler in ${PROTOBUF_PROTOC_C_EXECUTABLE}")
-endif ()
-include_directories(${PROTOBUF_C_INCLUDE_DIRS})
+endif()
+
+# Note: Include dirs are added per-target via target_include_directories
+# using ${PROTOBUF_C_INCLUDE_DIRS}
diff --git a/cmake/dependencies/robustmutex.cmake b/cmake/dependencies/system/robustmutex.cmake
index 94aec8f0..89b7325b 100644
--- a/cmake/dependencies/robustmutex.cmake
+++ b/cmake/dependencies/system/robustmutex.cmake
@@ -3,16 +3,16 @@ list(APPEND CMAKE_REQUIRED_DEFINITIONS -D__XSI_VISIBLE=500)
list(APPEND CMAKE_REQUIRED_LIBRARIES pthread)
check_symbol_exists(pthread_mutexattr_setrobust pthread.h HAVE_ROBUST_MUTEX)
-if (HAVE_ROBUST_MUTEX)
+if(HAVE_ROBUST_MUTEX)
set(DISABLE_ROBUST_MUTEXES FALSE CACHE BOOL "Disable robust mutex support")
- if (NOT DISABLE_ROBUST_MUTEXES)
+ if(NOT DISABLE_ROBUST_MUTEXES)
message(STATUS "Robust mutex support enabled")
set(HAVE_ROBUST_MUTEX TRUE)
- else ()
+ else()
message(STATUS "Robust mutex support disabled by user")
unset(HAVE_ROBUST_MUTEX)
- endif ()
+ endif()
else()
message(STATUS "Robust mutex support not available")
unset(HAVE_ROBUST_MUTEX)
-endif ()
+endif()
diff --git a/cmake/dependencies/system/sysrandom.cmake b/cmake/dependencies/system/sysrandom.cmake
new file mode 100644
index 00000000..dc8443a1
--- /dev/null
+++ b/cmake/dependencies/system/sysrandom.cmake
@@ -0,0 +1,14 @@
+if(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
+ set(SYS_RND_HDR "")
+else()
+ find_path(SYS_RND_HDR sys/random.h PATH /usr/include/ /usr/local/include/)
+ if(SYS_RND_HDR)
+ message(STATUS "Found sys/random.h in ${SYS_RND_HDR}")
+ set(HAVE_SYS_RANDOM TRUE)
+ else()
+ set(SYS_RND_HDR "")
+ unset(HAVE_SYS_RANDOM)
+ endif()
+endif()
+
+mark_as_advanced(SYS_RND_HDR)
diff --git a/cmake/dependencies/systemlibraries.cmake b/cmake/dependencies/systemlibraries.cmake
deleted file mode 100644
index e00266d6..00000000
--- a/cmake/dependencies/systemlibraries.cmake
+++ /dev/null
@@ -1,20 +0,0 @@
-if (NOT APPLE)
- find_library(LIBRT_LIBRARIES rt)
- if (NOT LIBRT_LIBRARIES)
- message(FATAL_ERROR "Could not find librt")
- endif ()
-else ()
- set(LIBRT_LIBRARIES "")
-endif ()
-
-find_library(LIBPTHREAD_LIBRARIES pthread)
-if (NOT LIBPTHREAD_LIBRARIES)
- message(FATAL_ERROR "Could not find libpthread")
-endif ()
-
-find_library(LIBM_LIBRARIES m)
-if (NOT LIBM_LIBRARIES)
- message(FATAL_ERROR "Could not find libm")
-endif ()
-
-mark_as_advanced(LIBRT_LIBRARIES LIBPTHREAD_LIBRARIES LIBM_LIBRARIES)
diff --git a/cmake/dependencies/udp/ddns.cmake b/cmake/dependencies/udp/ddns.cmake
new file mode 100644
index 00000000..e8208e47
--- /dev/null
+++ b/cmake/dependencies/udp/ddns.cmake
@@ -0,0 +1,31 @@
+# DDNS (Dynamic DNS) support detection
+# Requires nsupdate and nslookup tools
+
+find_program(NSUPDATE_EXECUTABLE
+ NAMES nsupdate
+ DOC "The nsupdate tool that enables DDNS")
+
+find_program(NSLOOKUP_EXECUTABLE
+ NAMES nslookup
+ DOC "The nslookup tool that resolves DNS names")
+
+mark_as_advanced(NSLOOKUP_EXECUTABLE NSUPDATE_EXECUTABLE)
+
+if(NSLOOKUP_EXECUTABLE AND NSUPDATE_EXECUTABLE)
+ set(DISABLE_DDNS FALSE CACHE BOOL "Disable DDNS support")
+ if(NOT DISABLE_DDNS)
+ message(STATUS "DDNS support enabled")
+ set(HAVE_DDNS TRUE CACHE INTERNAL "Dynamic DNS support available")
+ else()
+ message(STATUS "DDNS support disabled by user")
+ unset(HAVE_DDNS CACHE)
+ endif()
+else()
+ if(NSLOOKUP_EXECUTABLE)
+ message(STATUS "Install nsupdate to enable DDNS support")
+ elseif(NSUPDATE_EXECUTABLE)
+ message(STATUS "Install nslookup to enable DDNS support")
+ else()
+ message(STATUS "Install nslookup and nsupdate to enable DDNS support")
+ endif()
+endif()
diff --git a/cmake/doc.cmake b/cmake/doc.cmake
index 16991f82..f75cde5b 100644
--- a/cmake/doc.cmake
+++ b/cmake/doc.cmake
@@ -28,20 +28,12 @@ set(MAN_NAMES
irm.8
)
-macro(INSTALL_MAN __mans)
- foreach (_man ${ARGV})
- string(REGEX REPLACE "^.+[.]([1-9]).gz" "\\1" _mansect ${_man})
- install(FILES ${_man} DESTINATION "${CMAKE_INSTALL_MANDIR}/man${_mansect}")
- endforeach (_man)
-endmacro(INSTALL_MAN __mans)
-
find_program(GZIP_EXECUTABLE
NAMES gzip
DOC "Will gzip the man pages")
-
mark_as_advanced(GZIP_EXECUTABLE)
-if (GZIP_EXECUTABLE)
+if(GZIP_EXECUTABLE)
# Create the doc output directory
file(MAKE_DIRECTORY ${DOC_BINARY_DIR})
@@ -59,6 +51,4 @@ if (GZIP_EXECUTABLE)
endforeach ()
add_custom_target(man ALL DEPENDS ${MAN_FILES})
-
- INSTALL_MAN(${MAN_FILES})
-endif ()
+endif()
diff --git a/cmake/include.cmake b/cmake/include.cmake
index c14d205d..ace51d0f 100644
--- a/cmake/include.cmake
+++ b/cmake/include.cmake
@@ -1,7 +1,6 @@
set(HEADERS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/include/ouroboros")
-set(SOCK_BUF_SIZE 10240 CACHE STRING
- "Size of the buffer used by the UNIX sockets for local IPC")
+# SOCK_BUF_SIZE is in cmake/config/global.cmake
configure_file("${CMAKE_SOURCE_DIR}/include/ouroboros/version.h.in"
"${CMAKE_BINARY_DIR}/include/ouroboros/version.h" @ONLY)
@@ -22,7 +21,4 @@ set(PUBLIC_HEADER_FILES
${HEADERS_SOURCE_DIR}/proto.h
${HEADERS_SOURCE_DIR}/qos.h
${CMAKE_BINARY_DIR}/include/ouroboros/version.h
- )
-
-install(FILES ${PUBLIC_HEADER_FILES}
- DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ouroboros)
+)
diff --git a/cmake/install.cmake b/cmake/install.cmake
index 21a8cd52..79714df2 100644
--- a/cmake/install.cmake
+++ b/cmake/install.cmake
@@ -1,12 +1,48 @@
# Installation configuration
-# Install pkg-config files
+include(CMakePackageConfigHelpers)
+
+# Public headers
+install(FILES ${PUBLIC_HEADER_FILES}
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ouroboros)
+
+# Man pages
+if(GZIP_EXECUTABLE)
+ foreach(_man ${MAN_FILES})
+ string(REGEX REPLACE "^.+[.]([1-9]).gz" "\\1" _mansect ${_man})
+ install(FILES ${_man} DESTINATION "${CMAKE_INSTALL_MANDIR}/man${_mansect}")
+ endforeach()
+endif()
+
+# pkg-config files
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ouroboros-dev.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ouroboros-irm.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+set(OUROBOROS_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/Ouroboros")
+
+install(EXPORT OuroborosTargets
+ FILE OuroborosTargets.cmake
+ NAMESPACE Ouroboros::
+ DESTINATION ${OUROBOROS_CMAKE_DIR})
+
+configure_package_config_file(
+ "${CMAKE_SOURCE_DIR}/cmake/OuroborosConfig.cmake.in"
+ "${CMAKE_BINARY_DIR}/OuroborosConfig.cmake"
+ INSTALL_DESTINATION ${OUROBOROS_CMAKE_DIR})
+
+write_basic_package_version_file(
+ "${CMAKE_BINARY_DIR}/OuroborosConfigVersion.cmake"
+ VERSION ${PACKAGE_VERSION}
+ COMPATIBILITY SameMajorVersion)
+
+install(FILES
+ "${CMAKE_BINARY_DIR}/OuroborosConfig.cmake"
+ "${CMAKE_BINARY_DIR}/OuroborosConfigVersion.cmake"
+ DESTINATION ${OUROBOROS_CMAKE_DIR})
+
# Systemd service file installation
set(SYSTEMD_INSTALL_FILES "DETECT" CACHE STRING
"Install systemd .service files (NO (never), DETECT (use pkg-config - default),\
@@ -15,50 +51,51 @@ set(SYSTEMD_UNITDIR_OVERRIDE "" CACHE PATH
"Path to install systemd files. When SYSTEMD_INSTALL_FILES == DETECT, this\
can be empty to automatically determine the path. Cannot be empty when FORCE.")
-if (SYSTEMD_INSTALL_FILES STREQUAL "DETECT" OR SYSTEMD_INSTALL_FILES STREQUAL "FORCE")
- if (SYSTEMD_INSTALL_FILES STREQUAL "DETECT")
- pkg_check_modules(SYSTEMD "systemd")
- if (SYSTEMD_FOUND)
- if ("${SYSTEMD_UNITDIR_OVERRIDE}" STREQUAL "")
+if(SYSTEMD_INSTALL_FILES STREQUAL "DETECT" OR SYSTEMD_INSTALL_FILES STREQUAL "FORCE")
+ if(SYSTEMD_INSTALL_FILES STREQUAL "DETECT")
+ if(PkgConfig_FOUND)
+ pkg_check_modules(SYSTEMD "systemd")
+ endif()
+ if(SYSTEMD_FOUND)
+ if(SYSTEMD_UNITDIR_OVERRIDE STREQUAL "")
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE}
--variable=systemdsystemunitdir systemd
OUTPUT_VARIABLE SYSTEMD_UNITDIR_INTERNAL)
string(REGEX REPLACE "[ \t\n]+" "" SYSTEMD_UNITDIR_INTERNAL
"${SYSTEMD_UNITDIR_INTERNAL}"
)
- else ()
+ else()
set(SYSTEMD_UNITDIR_INTERNAL "${SYSTEMD_UNITDIR_OVERRIDE}")
- endif ()
- else ()
+ endif()
+ else()
set(SYSTEMD_UNITDIR_INTERNAL "")
- endif ()
- elseif (SYSTEMD_INSTALL_FILES STREQUAL "FORCE")
- if ("${SYSTEMD_UNITDIR_OVERRIDE}" STREQUAL "")
+ endif()
+ elseif(SYSTEMD_INSTALL_FILES STREQUAL "FORCE")
+ if(SYSTEMD_UNITDIR_OVERRIDE STREQUAL "")
message(FATAL_ERROR "Systemd installation required by user, but no path\
provided with SYSTEMD_UNITDIR_OVERRIDE.")
- else ()
+ else()
set(SYSTEMD_UNITDIR_INTERNAL "${SYSTEMD_UNITDIR_OVERRIDE}")
- endif ()
+ endif()
endif()
- if (NOT ${SYSTEMD_UNITDIR_INTERNAL} STREQUAL "")
+ if(NOT SYSTEMD_UNITDIR_INTERNAL STREQUAL "")
message(STATUS "Systemd service installation enabled to: ${SYSTEMD_UNITDIR_INTERNAL}")
- if (LIBTOML_LIBRARIES AND NOT DISABLE_CONFIGFILE)
+ if(LIBTOML_LIBRARIES AND NOT DISABLE_CONFIGFILE)
set (CONFIGURE_STRING "--config ${OUROBOROS_CONFIG_DIR}/${OUROBOROS_CONFIG_FILE}")
- else ()
+ else()
set (CONFIGURE_STRING "")
- endif ()
- configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ouroboros.service.in"
- "${CMAKE_CURRENT_BINARY_DIR}/ouroboros.service" @ONLY)
- install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ouroboros.service"
+ endif()
+ configure_file("${CMAKE_SOURCE_DIR}/ouroboros.service.in"
+ "${CMAKE_BINARY_DIR}/ouroboros.service" @ONLY)
+ install(FILES "${CMAKE_BINARY_DIR}/ouroboros.service"
DESTINATION "${SYSTEMD_UNITDIR_INTERNAL}")
- endif ()
-else ()
+ endif()
+else()
message(STATUS "Systemd service installation disabled by user")
endif()
-# Uninstall target
configure_file("${CMAKE_SOURCE_DIR}/cmake/utils/CMakeUninstall.cmake.in"
- "${CMAKE_BINARY_DIR}/cmake/cmakeuninstall.cmake" IMMEDIATE @ONLY)
+ "${CMAKE_BINARY_DIR}/cmake/cmakeuninstall.cmake" @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cmake/cmakeuninstall.cmake)
diff --git a/cmake/ipcp.cmake b/cmake/ipcp.cmake
deleted file mode 100644
index 6839fcc2..00000000
--- a/cmake/ipcp.cmake
+++ /dev/null
@@ -1,10 +0,0 @@
-include(ipcp/ipcp)
-include(ipcp/eth)
-include(ipcp/udp)
-include(ipcp/local)
-include(ipcp/broadcast)
-include(ipcp/unicast)
-
-configure_file("${IPCP_SOURCE_DIR}/config.h.in"
- "${IPCP_BINARY_DIR}/config.h" @ONLY)
-
diff --git a/cmake/ipcp/broadcast.cmake b/cmake/ipcp/broadcast.cmake
deleted file mode 100644
index 20610a25..00000000
--- a/cmake/ipcp/broadcast.cmake
+++ /dev/null
@@ -1,22 +0,0 @@
-set(BROADCAST_SOURCE_DIR "${IPCP_SOURCE_DIR}/broadcast")
-
-set(IPCP_BROADCAST_TARGET ipcpd-broadcast CACHE INTERNAL "")
-
-set(IPCP_BROADCAST_MPL 100 CACHE STRING
- "Default maximum packet lifetime for the Broadcast IPCP, in ms")
-
-set(BROADCAST_SOURCES
- "${BROADCAST_SOURCE_DIR}/connmgr.c"
- "${BROADCAST_SOURCE_DIR}/dt.c"
- "${BROADCAST_SOURCE_DIR}/main.c"
-)
-
-add_executable(${IPCP_BROADCAST_TARGET}
- ${BROADCAST_SOURCES}
- ${IPCP_SOURCES}
- ${COMMON_SOURCES}
-)
-
-target_include_directories(${IPCP_BROADCAST_TARGET} PRIVATE ${IPCP_INCLUDE_DIRS})
-target_link_libraries(${IPCP_BROADCAST_TARGET} PUBLIC ouroboros-dev)
-install(TARGETS ${IPCP_BROADCAST_TARGET} RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
diff --git a/cmake/ipcp/eth.cmake b/cmake/ipcp/eth.cmake
deleted file mode 100644
index c14a1d6e..00000000
--- a/cmake/ipcp/eth.cmake
+++ /dev/null
@@ -1,42 +0,0 @@
-set(ETH_SOURCE_DIR "${IPCP_SOURCE_DIR}/eth")
-
-set(IPCP_ETH_LLC_TARGET ipcpd-eth-llc CACHE INTERNAL "")
-set(IPCP_ETH_DIX_TARGET ipcpd-eth-dix CACHE INTERNAL "")
-
-set(IPCP_ETH_RD_THR 1 CACHE STRING
- "Number of reader threads in Ethernet IPCP")
-set(IPCP_ETH_WR_THR 1 CACHE STRING
- "Number of writer threads in Ethernet IPCP")
-set(IPCP_ETH_QDISC_BYPASS false CACHE BOOL
- "Bypass the Qdisc in the kernel when using raw sockets")
-set(IPCP_ETH_LO_MTU 9000 CACHE STRING
- "Restrict Ethernet MTU over loopback interfaces")
-set(IPCP_ETH_MGMT_FRAME_SIZE 9000 CACHE STRING
- "Management frame buffer size for Ethernet IPCPs")
-set(IPCP_ETH_MPL 100 CACHE STRING
- "Default maximum packet lifetime for the Ethernet IPCPs, in ms")
-
-if (HAVE_RAW_SOCKETS OR HAVE_BPF OR HAVE_NETMAP)
- set(HAVE_ETH TRUE)
-else ()
- unset(HAVE_ETH)
-endif ()
-
-if (HAVE_ETH)
- add_executable(${IPCP_ETH_LLC_TARGET} "${ETH_SOURCE_DIR}/llc.c" ${IPCP_SOURCES})
- add_executable(${IPCP_ETH_DIX_TARGET} "${ETH_SOURCE_DIR}/dix.c" ${IPCP_SOURCES})
-
- foreach(target ${IPCP_ETH_LLC_TARGET} ${IPCP_ETH_DIX_TARGET})
- target_include_directories(${target} PRIVATE ${IPCP_INCLUDE_DIRS})
- if (HAVE_BPF AND NOT APPLE)
- target_include_directories(${target} PRIVATE ${BPF_C_INCLUDE_DIR})
- endif ()
- if (HAVE_NETMAP AND NOT APPLE)
- set_target_properties(${target} PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -std=c99")
- target_include_directories(${target} PRIVATE ${NETMAP_C_INCLUDE_DIR})
- endif ()
- target_link_libraries(${target} PUBLIC ouroboros-dev)
- endforeach()
-
- install(TARGETS ${IPCP_ETH_LLC_TARGET} ${IPCP_ETH_DIX_TARGET} RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
-endif ()
diff --git a/cmake/ipcp/ipcp.cmake b/cmake/ipcp/ipcp.cmake
deleted file mode 100644
index f821f481..00000000
--- a/cmake/ipcp/ipcp.cmake
+++ /dev/null
@@ -1,60 +0,0 @@
-set(IPCP_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src/ipcpd")
-set(IPCP_BINARY_DIR "${CMAKE_BINARY_DIR}/src/ipcpd")
-
-set(CONNMGR_RCV_TIMEOUT 1000 CACHE STRING
- "Timeout for the connection manager to wait for OCEP info (ms).")
-set(IPCP_DEBUG_LOCAL FALSE CACHE BOOL
- "Use PID as address for local debugging")
-set(IPCP_QOS_CUBE_BE_PRIO 50 CACHE STRING
- "Priority for best effort QoS cube (0-99)")
-set(IPCP_QOS_CUBE_VIDEO_PRIO 90 CACHE STRING
- "Priority for video QoS cube (0-99)")
-set(IPCP_QOS_CUBE_VOICE_PRIO 99 CACHE STRING
- "Priority for voice QoS cube (0-99)")
-set(IPCP_MIN_THREADS 4 CACHE STRING
- "Minimum number of worker threads in the IPCP")
-set(IPCP_ADD_THREADS 4 CACHE STRING
- "Number of extra threads to start when an IPCP faces thread starvation")
-set(IPCP_SCHED_THR_MUL 2 CACHE STRING
- "Number of scheduler threads per QoS cube")
-set(DISABLE_CORE_LOCK TRUE CACHE BOOL
- "Disable locking performance threads to a core")
-set(BUILD_CONTAINER FALSE CACHE BOOL
- "Disable thread priority setting for container compatibility")
-
-if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
- set(IPCP_LINUX_TIMERSLACK_NS 1000 CACHE STRING
- "Slack value for high resolution timers on Linux systems.")
-endif ()
-
-if ((IPCP_QOS_CUBE_BE_PRIO LESS 0) OR (IPCP_QOS_CUBE_BE_PRIO GREATER 99))
- message(FATAL_ERROR "Invalid priority for best effort QoS cube")
-endif ()
-
-if ((IPCP_QOS_CUBE_VIDEO_PRIO LESS 0) OR (IPCP_QOS_CUBE_VIDEO_PRIO GREATER 99))
- message(FATAL_ERROR "Invalid priority for video QoS cube")
-endif ()
-
-if ((IPCP_QOS_CUBE_VOICE_PRIO LESS 0) OR (IPCP_QOS_CUBE_VOICE_PRIO GREATER 99))
- message(FATAL_ERROR "Invalid priority for voice QoS cube")
-endif ()
-
-if ((DHT_ENROLL_SLACK LESS 0) OR (DHT_ENROLL_SLACK GREATER 999))
- message(FATAL_ERROR "Invalid DHT slack value")
-endif ()
-
-set(IPCP_SOURCES
- "${IPCP_SOURCE_DIR}/ipcp.c"
- "${IPCP_SOURCE_DIR}/shim-data.c"
-)
-
-set(COMMON_SOURCES
- "${IPCP_SOURCE_DIR}/common/enroll.c"
-)
-
-set(IPCP_INCLUDE_DIRS
- ${IPCP_SOURCE_DIR}
- ${IPCP_BINARY_DIR}
- ${CMAKE_SOURCE_DIR}/include
- ${CMAKE_BINARY_DIR}/include
-)
diff --git a/cmake/ipcp/local.cmake b/cmake/ipcp/local.cmake
deleted file mode 100644
index 9e320aad..00000000
--- a/cmake/ipcp/local.cmake
+++ /dev/null
@@ -1,11 +0,0 @@
-set(LOCAL_SOURCE_DIR "${IPCP_SOURCE_DIR}/local")
-
-set(IPCP_LOCAL_TARGET ipcpd-local CACHE INTERNAL "")
-
-set(IPCP_LOCAL_MPL 100 CACHE STRING
- "Default maximum packet lifetime for the Local IPCP, in ms")
-
-add_executable(${IPCP_LOCAL_TARGET} "${LOCAL_SOURCE_DIR}/main.c" ${IPCP_SOURCES})
-target_include_directories(${IPCP_LOCAL_TARGET} PRIVATE ${IPCP_INCLUDE_DIRS})
-target_link_libraries(${IPCP_LOCAL_TARGET} PUBLIC ouroboros-dev)
-install(TARGETS ${IPCP_LOCAL_TARGET} RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
diff --git a/cmake/ipcp/udp.cmake b/cmake/ipcp/udp.cmake
deleted file mode 100644
index 7195dfa1..00000000
--- a/cmake/ipcp/udp.cmake
+++ /dev/null
@@ -1,51 +0,0 @@
-set(UDP_SOURCE_DIR "${IPCP_SOURCE_DIR}/udp")
-
-set(IPCP_UDP4_TARGET ipcpd-udp4 CACHE INTERNAL "")
-set(IPCP_UDP6_TARGET ipcpd-udp6 CACHE INTERNAL "")
-
-set(IPCP_UDP_RD_THR 3 CACHE STRING
- "Number of reader threads in UDP IPCPs")
-set(IPCP_UDP_WR_THR 3 CACHE STRING
- "Number of writer threads in UDP IPCPs")
-set(IPCP_UDP_MPL 5000 CACHE STRING
- "Default maximum packet lifetime for the UDP IPCPs, in ms")
-
-# Find nsupdate and nslookup for DDNS support
-find_program(NSUPDATE_EXECUTABLE
- NAMES nsupdate
- DOC "The nsupdate tool that enables DDNS")
-
-find_program(NSLOOKUP_EXECUTABLE
- NAMES nslookup
- DOC "The nslookup tool that resolves DNS names")
-
-mark_as_advanced(NSLOOKUP_EXECUTABLE NSUPDATE_EXECUTABLE)
-
-if (NSLOOKUP_EXECUTABLE AND NSUPDATE_EXECUTABLE)
- set(DISABLE_DDNS FALSE CACHE BOOL "Disable DDNS support")
- if (NOT DISABLE_DDNS)
- message(STATUS "DDNS support enabled")
- set(HAVE_DDNS TRUE CACHE INTERNAL "")
- else ()
- message(STATUS "DDNS support disabled by user")
- unset(HAVE_DDNS CACHE)
- endif ()
-else ()
- if (NSLOOKUP_EXECUTABLE)
- message(STATUS "Install nsupdate to enable DDNS support")
- elseif (NSUPDATE_EXECUTABLE)
- message(STATUS "Install nslookup to enable DDNS support")
- else ()
- message(STATUS "Install nslookup and nsupdate to enable DDNS support")
- endif ()
-endif ()
-
-add_executable(${IPCP_UDP4_TARGET} "${UDP_SOURCE_DIR}/udp4.c" ${IPCP_SOURCES})
-add_executable(${IPCP_UDP6_TARGET} "${UDP_SOURCE_DIR}/udp6.c" ${IPCP_SOURCES})
-
-foreach(target ${IPCP_UDP4_TARGET} ${IPCP_UDP6_TARGET})
- target_include_directories(${target} PRIVATE ${IPCP_INCLUDE_DIRS})
- target_link_libraries(${target} PUBLIC ouroboros-dev)
-endforeach()
-
-install(TARGETS ${IPCP_UDP4_TARGET} ${IPCP_UDP6_TARGET} RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
diff --git a/cmake/ipcp/unicast.cmake b/cmake/ipcp/unicast.cmake
deleted file mode 100644
index 2a2f7a3f..00000000
--- a/cmake/ipcp/unicast.cmake
+++ /dev/null
@@ -1,50 +0,0 @@
-set(UNICAST_SOURCE_DIR "${IPCP_SOURCE_DIR}/unicast")
-set(UNICAST_BINARY_DIR "${IPCP_BINARY_DIR}/unicast")
-
-set(IPCP_UNICAST_TARGET ipcpd-unicast CACHE INTERNAL "")
-
-set(IPCP_UNICAST_MPL 100 CACHE STRING
- "Default maximum packet lifetime for the Unicast IPCP, in ms")
-set(PFT_SIZE 256 CACHE STRING
- "Prefix forwarding table size for the Unicast IPCP")
-set(DEBUG_PROTO_DHT FALSE CACHE BOOL
- "Add DHT protocol debug logging")
-set(DEBUG_PROTO_LS FALSE CACHE BOOL
- "Add link state protocol debug logging")
-
-# Generate DHT protobuf files
-protobuf_generate_c(DHT_PROTO_SRCS DHT_PROTO_HDRS "${UNICAST_SOURCE_DIR}/dir/dht.proto")
-
-set (UNICAST_SOURCES
- "${UNICAST_SOURCE_DIR}/addr-auth.c"
- "${UNICAST_SOURCE_DIR}/ca.c"
- "${UNICAST_SOURCE_DIR}/connmgr.c"
- "${UNICAST_SOURCE_DIR}/dir.c"
- "${UNICAST_SOURCE_DIR}/dt.c"
- "${UNICAST_SOURCE_DIR}/fa.c"
- "${UNICAST_SOURCE_DIR}/main.c"
- "${UNICAST_SOURCE_DIR}/pff.c"
- "${UNICAST_SOURCE_DIR}/routing.c"
- "${UNICAST_SOURCE_DIR}/psched.c"
- "${UNICAST_SOURCE_DIR}/addr-auth/flat.c"
- "${UNICAST_SOURCE_DIR}/ca/mb-ecn.c"
- "${UNICAST_SOURCE_DIR}/ca/nop.c"
- "${UNICAST_SOURCE_DIR}/dir/dht.c"
- "${UNICAST_SOURCE_DIR}/pff/simple.c"
- "${UNICAST_SOURCE_DIR}/pff/alternate.c"
- "${UNICAST_SOURCE_DIR}/pff/multipath.c"
- "${UNICAST_SOURCE_DIR}/pff/pft.c"
- "${UNICAST_SOURCE_DIR}/routing/link-state.c"
- "${UNICAST_SOURCE_DIR}/routing/graph.c"
-)
-
-add_executable(${IPCP_UNICAST_TARGET}
- ${UNICAST_SOURCES}
- ${IPCP_SOURCES}
- ${COMMON_SOURCES}
- ${DHT_PROTO_SRCS}
-)
-target_include_directories(${IPCP_UNICAST_TARGET} PRIVATE ${IPCP_INCLUDE_DIRS})
-target_include_directories(${IPCP_UNICAST_TARGET} PRIVATE "${UNICAST_SOURCE_DIR}")
-target_link_libraries(${IPCP_UNICAST_TARGET} PUBLIC ouroboros-dev)
-install(TARGETS ${IPCP_UNICAST_TARGET} RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
diff --git a/cmake/irmd.cmake b/cmake/irmd.cmake
deleted file mode 100644
index f02f37d6..00000000
--- a/cmake/irmd.cmake
+++ /dev/null
@@ -1,125 +0,0 @@
-set(IRMD_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src/irmd")
-set(IRMD_BINARY_DIR "${CMAKE_BINARY_DIR}/src/irmd")
-
-set(OUROBOROS_CONFIG_DIR /etc/ouroboros CACHE STRING
- "Configuration directory (should be absolute)")
-
-# Configuration file support
-set(OUROBOROS_SECURITY_DIR "${OUROBOROS_CONFIG_DIR}/security" CACHE STRING
- "Security directory holding authentication information")
-set(OUROBOROS_CA_CRT_DIR "${OUROBOROS_SECURITY_DIR}/cacert" CACHE STRING
- "Directory holding trusted CA certificates")
-set(OUROBOROS_SRV_CRT_DIR "${OUROBOROS_SECURITY_DIR}/server" CACHE STRING
- "Directory holding server certificates")
-set(OUROBOROS_CLI_CRT_DIR "${OUROBOROS_SECURITY_DIR}/client" CACHE STRING
- "Directory holding client certificates")
-set(OUROBOROS_UNTRUSTED_DIR "${OUROBOROS_SECURITY_DIR}/untrusted" CACHE STRING
- "Directory holding untrusted intermediate certificates")
-
-# IRMd timeouts and parameters
-set(IRMD_REQ_ARR_TIMEOUT 1000 CACHE STRING
- "Timeout for an application to respond to a new flow (ms)")
-set(BOOTSTRAP_TIMEOUT 5000 CACHE STRING
- "Timeout for an IPCP to bootstrap (ms)")
-set(ENROLL_TIMEOUT 20000 CACHE STRING
- "Timeout for an IPCP to enroll (ms)")
-set(REG_TIMEOUT 20000 CACHE STRING
- "Timeout for registering a name (ms)")
-set(QUERY_TIMEOUT 200 CACHE STRING
- "Timeout to query a name with an IPCP (ms)")
-set(CONNECT_TIMEOUT 20000 CACHE STRING
- "Timeout to connect an IPCP to another IPCP (ms)")
-set(FLOW_ALLOC_TIMEOUT 20000 CACHE STRING
- "Timeout for a flow allocation response (ms)")
-set(OAP_REPLAY_TIMER 20 CACHE STRING
- "OAP replay protection window (s)")
-set(IRMD_MIN_THREADS 8 CACHE STRING
- "Minimum number of worker threads in the IRMd")
-set(IRMD_ADD_THREADS 8 CACHE STRING
- "Number of extra threads to start when the IRMD faces thread starvation")
-set(IRMD_PKILL_TIMEOUT 30 CACHE STRING
- "Number of seconds to wait before sending SIGKILL to subprocesses on exit")
-set(IRMD_KILL_ALL_PROCESSES TRUE CACHE BOOL
- "Kill all processes on exit")
-set(DEBUG_PROTO_OAP FALSE CACHE BOOL
- "Add Flow allocation protocol message output to IRMd debug logging")
-
-# Configuration file support (libtoml)
-if (LIBTOML_LIBRARIES)
- set(DISABLE_CONFIGFILE FALSE CACHE BOOL
- "Disable configuration file support")
- if (NOT DISABLE_CONFIGFILE)
- set(OUROBOROS_CONFIG_FILE irmd.conf CACHE STRING
- "Name of the IRMd configuration file")
- set(HAVE_TOML TRUE)
- message(STATUS "Configuration file support enabled")
- message(STATUS "Configuration directory: ${OUROBOROS_CONFIG_DIR}")
- set(INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
- configure_file("${CMAKE_SOURCE_DIR}/irmd.conf.in"
- "${CMAKE_BINARY_DIR}/${OUROBOROS_CONFIG_FILE}.example" @ONLY)
- configure_file("${CMAKE_SOURCE_DIR}/enc.conf.in"
- "${CMAKE_BINARY_DIR}/enc.conf.example" @ONLY)
- install(FILES "${CMAKE_BINARY_DIR}/${OUROBOROS_CONFIG_FILE}.example"
- DESTINATION "${OUROBOROS_CONFIG_DIR}")
- install(FILES "${CMAKE_BINARY_DIR}/enc.conf.example"
- DESTINATION "${OUROBOROS_CONFIG_DIR}")
- install(CODE "
- if (NOT EXISTS \"${OUROBOROS_CONFIG_DIR}/${OUROBOROS_CONFIG_FILE}\")
- file(WRITE \"${OUROBOROS_CONFIG_DIR}/${OUROBOROS_CONFIG_FILE}\" \"\")
- endif()
- ")
- unset(INSTALL_DIR)
- else ()
- message(STATUS "Configuration file support disabled by user")
- unset(OUROBOROS_CONFIG_FILE CACHE)
- set(HAVE_TOML FALSE)
- endif ()
-else ()
- message(STATUS "Install tomlc99 for config file support")
- message(STATUS " https://github.com/cktan/tomlc99")
- unset(HAVE_TOML)
-endif ()
-
-configure_file("${IRMD_SOURCE_DIR}/config.h.in"
- "${IRMD_BINARY_DIR}/config.h" @ONLY)
-
-set(IRMD_SOURCES
- "${IRMD_SOURCE_DIR}/ipcp.c"
- "${IRMD_SOURCE_DIR}/configfile.c"
- "${IRMD_SOURCE_DIR}/main.c"
- "${IRMD_SOURCE_DIR}/oap/io.c"
- "${IRMD_SOURCE_DIR}/oap/hdr.c"
- "${IRMD_SOURCE_DIR}/oap/auth.c"
- "${IRMD_SOURCE_DIR}/oap/srv.c"
- "${IRMD_SOURCE_DIR}/oap/cli.c"
- "${IRMD_SOURCE_DIR}/reg/flow.c"
- "${IRMD_SOURCE_DIR}/reg/ipcp.c"
- "${IRMD_SOURCE_DIR}/reg/proc.c"
- "${IRMD_SOURCE_DIR}/reg/prog.c"
- "${IRMD_SOURCE_DIR}/reg/name.c"
- "${IRMD_SOURCE_DIR}/reg/reg.c"
-)
-
-add_executable(irmd ${IRMD_SOURCES})
-
-target_include_directories(irmd PRIVATE
- "${IRMD_SOURCE_DIR}"
- "${IRMD_BINARY_DIR}"
- "${CMAKE_SOURCE_DIR}/include"
- "${CMAKE_BINARY_DIR}/include")
-
-target_link_libraries(irmd PUBLIC ouroboros-common)
-if (LIBTOML_LIBRARIES)
- target_link_libraries(irmd PUBLIC ${LIBTOML_LIBRARIES})
-endif ()
-
-if (HAVE_TOML)
- target_include_directories(irmd PRIVATE ${LIBTOML_INCLUDE})
-endif ()
-
-include(utils/AddCompileFlags)
-if (CMAKE_BUILD_TYPE MATCHES "Debug*")
- add_compile_flags(irmd -DCONFIG_OUROBOROS_DEBUG)
-endif ()
-
-install(TARGETS irmd RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
diff --git a/cmake/lib.cmake b/cmake/lib.cmake
deleted file mode 100644
index 284c19ee..00000000
--- a/cmake/lib.cmake
+++ /dev/null
@@ -1,11 +0,0 @@
-include(lib/lib)
-include(lib/common)
-include(lib/dev)
-include(lib/irm)
-include(lib/ssm)
-
-configure_file("${LIB_SOURCE_DIR}/config.h.in"
- "${LIB_BINARY_DIR}/config.h" @ONLY)
-
-configure_file("${LIB_SOURCE_DIR}/ssm/ssm.h.in"
- "${LIB_BINARY_DIR}/ssm.h" @ONLY)
diff --git a/cmake/lib/common.cmake b/cmake/lib/common.cmake
deleted file mode 100644
index b0898950..00000000
--- a/cmake/lib/common.cmake
+++ /dev/null
@@ -1,124 +0,0 @@
-# Common library configuration
-
-set(LIB_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src/lib")
-set(LIB_BINARY_DIR "${CMAKE_BINARY_DIR}/src/lib")
-
-# Protobuf files
-set_source_files_properties(
- "${LIB_SOURCE_DIR}/pb/model.proto"
- "${LIB_SOURCE_DIR}/pb/ipcp_config.proto"
- "${LIB_SOURCE_DIR}/pb/enroll.proto"
- "${LIB_SOURCE_DIR}/pb/cep.proto"
- "${LIB_SOURCE_DIR}/pb/irm.proto"
- "${LIB_SOURCE_DIR}/pb/ipcp.proto"
- PROPERTIES
- COMPILE_FLAGS "-I${LIB_SOURCE_DIR}/pb"
-)
-
-protobuf_generate_c(MODEL_PROTO_SRCS MODEL_PROTO_HDRS
- "${LIB_SOURCE_DIR}/pb/model.proto")
-protobuf_generate_c(IPCP_CONFIG_PROTO_SRCS IPCP_CONFIG_PROTO_HDRS
- "${LIB_SOURCE_DIR}/pb/ipcp_config.proto")
-protobuf_generate_c(ENROLL_PROTO_SRCS ENROLL_PROTO_HDRS
- "${LIB_SOURCE_DIR}/pb/enroll.proto")
-protobuf_generate_c(CEP_PROTO_SRCS CEP_PROTO_HDRS
- "${LIB_SOURCE_DIR}/pb/cep.proto")
-protobuf_generate_c(IRM_PROTO_SRCS IRM_PROTO_HDRS
- "${LIB_SOURCE_DIR}/pb/irm.proto")
-protobuf_generate_c(IPCP_PROTO_SRCS IPCP_PROTO_HDRS
- "${LIB_SOURCE_DIR}/pb/ipcp.proto")
-
-# Common library source files
-set(SOURCE_FILES_COMMON
- bitmap.c
- btree.c
- crc32.c
- crypt.c
- hash.c
- list.c
- lockfile.c
- logs.c
- md5.c
- notifier.c
- protobuf.c
- qoscube.c
- random.c
- rib.c
- serdes-irm.c
- serdes-oep.c
- sha3.c
- ssm/flow_set.c
- ssm/rbuff.c
- ssm/pool.c
- sockets.c
- tpm.c
- utils.c
-)
-
-# Convert relative paths to absolute
-set(SOURCE_FILES_COMMON_ABS)
-foreach(src ${SOURCE_FILES_COMMON})
- list(APPEND SOURCE_FILES_COMMON_ABS "${LIB_SOURCE_DIR}/${src}")
-endforeach()
-
-if (HAVE_OPENSSL)
- set(OPENSSL_SOURCES "${LIB_SOURCE_DIR}/crypt/openssl.c")
-else()
- set(OPENSSL_SOURCES "")
-endif()
-
-add_library(ouroboros-common SHARED
- ${SOURCE_FILES_COMMON_ABS}
- ${IRM_PROTO_SRCS}
- ${IPCP_PROTO_SRCS}
- ${IPCP_CONFIG_PROTO_SRCS}
- ${MODEL_PROTO_SRCS}
- ${ENROLL_PROTO_SRCS}
- ${OPENSSL_SOURCES})
-
-set_target_properties(ouroboros-common PROPERTIES
- VERSION ${PACKAGE_VERSION}
- SOVERSION ${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR})
-
-include(utils/AddCompileFlags)
-if (CMAKE_BUILD_TYPE MATCHES "Debug*")
- add_compile_flags(ouroboros-common -DCONFIG_OUROBOROS_DEBUG)
-endif ()
-
-target_include_directories(ouroboros-common PUBLIC
- ${LIB_SOURCE_DIR}
- ${LIB_BINARY_DIR}
- ${CMAKE_SOURCE_DIR}/include
- ${CMAKE_BINARY_DIR}/include
- ${CMAKE_BINARY_DIR}
- ${PROTOBUF_C_INCLUDE_DIRS}
- ${SYS_RND_HDR})
-
-if (LIBGCRYPT_INCLUDE_DIR)
- target_include_directories(ouroboros-common PUBLIC ${LIBGCRYPT_INCLUDE_DIR})
-endif ()
-
-if (OPENSSL_INCLUDE_DIR)
- target_include_directories(ouroboros-common PUBLIC ${OPENSSL_INCLUDE_DIR})
-endif ()
-
-
-target_link_libraries(ouroboros-common
- ${LIBRT_LIBRARIES}
- ${LIBPTHREAD_LIBRARIES}
- ${PROTOBUF_C_LIBRARY})
-
-if (OPENSSL_CRYPTO_LIBRARY)
- target_link_libraries(ouroboros-common ${OPENSSL_CRYPTO_LIBRARY})
-endif ()
-
-if (LIBGCRYPT_LIBRARIES)
- target_link_libraries(ouroboros-common ${LIBGCRYPT_LIBRARIES})
-endif ()
-
-if (FUSE_LIBRARIES)
- target_link_libraries(ouroboros-common ${FUSE_LIBRARIES})
-endif ()
-
-install(TARGETS ouroboros-common LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
-
diff --git a/cmake/lib/dev.cmake b/cmake/lib/dev.cmake
deleted file mode 100644
index 21fe140d..00000000
--- a/cmake/lib/dev.cmake
+++ /dev/null
@@ -1,37 +0,0 @@
-set(SOURCE_FILES_DEV
- cep.c
- dev.c
-)
-
-# Convert relative paths to absolute
-set(SOURCE_FILES_DEV_ABS)
-foreach(src ${SOURCE_FILES_DEV})
- list(APPEND SOURCE_FILES_DEV_ABS "${LIB_SOURCE_DIR}/${src}")
-endforeach()
-
-add_library(ouroboros-dev SHARED
- ${SOURCE_FILES_DEV_ABS}
- ${CEP_PROTO_SRCS})
-
-set_target_properties(ouroboros-dev PROPERTIES
- VERSION ${PACKAGE_VERSION}
- SOVERSION ${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR})
-
-if (CMAKE_BUILD_TYPE MATCHES "Debug*")
- add_compile_flags(ouroboros-dev -DCONFIG_OUROBOROS_DEBUG)
-endif ()
-
-target_include_directories(ouroboros-dev PUBLIC
- ${LIB_SOURCE_DIR}
- ${LIB_BINARY_DIR}
- ${CMAKE_SOURCE_DIR}/include
- ${CMAKE_BINARY_DIR}/include
- ${CMAKE_BINARY_DIR}
- ${PROTOBUF_C_INCLUDE_DIRS}
- ${SYS_RND_HDR}
- ${LIBGCRYPT_INCLUDE_DIR}
- ${OPENSSL_INCLUDE_DIR})
-
-target_link_libraries(ouroboros-dev ouroboros-common)
-
-install(TARGETS ouroboros-dev LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
diff --git a/cmake/lib/irm.cmake b/cmake/lib/irm.cmake
deleted file mode 100644
index 5e336b31..00000000
--- a/cmake/lib/irm.cmake
+++ /dev/null
@@ -1,34 +0,0 @@
-set(SOURCE_FILES_IRM
- irm.c
-)
-
-# Convert relative paths to absolute
-set(SOURCE_FILES_IRM_ABS)
-foreach(src ${SOURCE_FILES_IRM})
- list(APPEND SOURCE_FILES_IRM_ABS "${LIB_SOURCE_DIR}/${src}")
-endforeach()
-
-add_library(ouroboros-irm SHARED ${SOURCE_FILES_IRM_ABS})
-
-set_target_properties(ouroboros-irm PROPERTIES
- VERSION ${PACKAGE_VERSION}
- SOVERSION ${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR})
-
-if (CMAKE_BUILD_TYPE MATCHES "Debug*")
- add_compile_flags(ouroboros-irm -DCONFIG_OUROBOROS_DEBUG)
-endif ()
-
-target_include_directories(ouroboros-irm PUBLIC
- ${LIB_SOURCE_DIR}
- ${LIB_BINARY_DIR}
- ${CMAKE_SOURCE_DIR}/include
- ${CMAKE_BINARY_DIR}/include
- ${CMAKE_BINARY_DIR}
- ${PROTOBUF_C_INCLUDE_DIRS}
- ${SYS_RND_HDR}
- ${LIBGCRYPT_INCLUDE_DIR}
- ${OPENSSL_INCLUDE_DIR})
-
-target_link_libraries(ouroboros-irm ouroboros-common)
-
-install(TARGETS ouroboros-irm LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
diff --git a/cmake/lib/ssm.cmake b/cmake/lib/ssm.cmake
deleted file mode 100644
index 71790a4a..00000000
--- a/cmake/lib/ssm.cmake
+++ /dev/null
@@ -1,89 +0,0 @@
-# Pool size configuration for Ouroboros secure shared memory
-# This file defines the allocation parameters for the
-# secure shared memory pool allocator
-
-# Shared memory pool naming configuration
-set(SSM_PREFIX "o7s.ssm" CACHE STRING
- "Prefix for secure shared memory pools")
-set(SSM_GSMP_SUFFIX ".gsmp" CACHE STRING
- "Suffix for Group Shared Memory Pool")
-set(SSM_PPP_SUFFIX ".ppp" CACHE STRING
- "Suffix for Process Private Pool")
-
-set(SSM_POOL_NAME "/${SHM_PREFIX}.pool" CACHE INTERNAL
- "Name for the main POSIX shared memory pool")
-set(SSM_POOL_BLOCKS 16384 CACHE STRING
- "Number of blocks in SSM packet pool, must be a power of 2")
-set(SSM_PK_BUFF_HEADSPACE 256 CACHE STRING
- "Bytes of headspace to reserve for future headers")
-set(SSM_PK_BUFF_TAILSPACE 32 CACHE STRING
- "Bytes of tailspace to reserve for future tails")
-set(SSM_RBUFF_SIZE 1024 CACHE STRING
- "Number of blocks in rbuff buffer, must be a power of 2")
-set(SSM_RBUFF_PREFIX "/${SHM_PREFIX}.rbuff." CACHE INTERNAL
- "Prefix for rbuff POSIX shared memory filenames")
-set(SSM_FLOW_SET_PREFIX "/${SHM_PREFIX}.set." CACHE INTERNAL
- "Prefix for the POSIX shared memory flow set")
-
-# Pool blocks per size class
-# This determines how many blocks of each size are preallocated in the pool
-# Higher values reduce allocation failures but increase memory usage
-set(SSM_POOL_256_BLOCKS 1024 CACHE STRING
- "Number of 256B blocks in pool")
-set(SSM_POOL_512_BLOCKS 768 CACHE STRING
- "Number of 512B blocks in pool")
-set(SSM_POOL_1K_BLOCKS 512 CACHE STRING
- "Number of 1KB blocks in pool")
-set(SSM_POOL_2K_BLOCKS 384 CACHE STRING
- "Number of 2KB blocks in pool")
-set(SSM_POOL_4K_BLOCKS 256 CACHE STRING
- "Number of 4KB blocks in pool")
-set(SSM_POOL_16K_BLOCKS 128 CACHE STRING
- "Number of 16KB blocks in pool")
-set(SSM_POOL_64K_BLOCKS 64 CACHE STRING
- "Number of 64KB blocks in pool")
-set(SSM_POOL_256K_BLOCKS 32 CACHE STRING
- "Number of 256KB blocks in pool")
-set(SSM_POOL_1M_BLOCKS 16 CACHE STRING
- "Number of 1MB blocks in pool")
-
-# Number of shards per size class for reducing contention
-set(SSM_POOL_SHARDS 4 CACHE STRING
- "Number of allocator shards per size class")
-
-# SSM packet buffer overhead - computed at compile time via sizeof()
-# Defined in config.h.in as sizeof(_ssm_memory_block) + sizeof(_ssm_pk_buff)
-# This makes it portable across platforms with different pid_t sizes and padding
-
-# Total shared memory pool size calculation
-math(EXPR SSM_POOL_TOTAL_SIZE
- "(1 << 8) * ${SSM_POOL_256_BLOCKS} + \
- (1 << 9) * ${SSM_POOL_512_BLOCKS} + \
- (1 << 10) * ${SSM_POOL_1K_BLOCKS} + \
- (1 << 11) * ${SSM_POOL_2K_BLOCKS} + \
- (1 << 12) * ${SSM_POOL_4K_BLOCKS} + \
- (1 << 14) * ${SSM_POOL_16K_BLOCKS} + \
- (1 << 16) * ${SSM_POOL_64K_BLOCKS} + \
- (1 << 18) * ${SSM_POOL_256K_BLOCKS} + \
- (1 << 20) * ${SSM_POOL_1M_BLOCKS}")
-
-set(SSM_POOL_TOTAL_SIZE ${SSM_POOL_TOTAL_SIZE} CACHE INTERNAL
- "Total shared memory pool size in bytes")
-
-include(utils/HumanReadable)
-format_bytes_human_readable(${SSM_POOL_TOTAL_SIZE} SSM_POOL_SIZE_DISPLAY)
-
-# Display configuration summary
-message(STATUS "Secure Shared Memory Pool Configuration:")
-message(STATUS " Pool prefix: ${SSM_PREFIX}")
-message(STATUS " Size classes: "
- "256B, 512B, 1KiB, 2KiB, 4KiB, 16KiB, 64KiB, 256KiB, 1MiB")
-message(STATUS " Max allocation: 1 MB")
-message(STATUS " Total pool size: ${SSM_POOL_SIZE_DISPLAY} "
- "(${SSM_POOL_TOTAL_SIZE} bytes)")
-message(STATUS " Shards per class: ${SSM_POOL_SHARDS}")
-message(STATUS " Blocks per class: ${SSM_POOL_256_BLOCKS}, "
- "${SSM_POOL_512_BLOCKS}, ${SSM_POOL_1K_BLOCKS}, "
- "${SSM_POOL_2K_BLOCKS}, ${SSM_POOL_4K_BLOCKS}, "
- "${SSM_POOL_16K_BLOCKS}, ${SSM_POOL_64K_BLOCKS}, "
- "${SSM_POOL_256K_BLOCKS}, ${SSM_POOL_1M_BLOCKS}")
diff --git a/cmake/package.cmake b/cmake/package.cmake
index d45222dc..71105ee8 100644
--- a/cmake/package.cmake
+++ b/cmake/package.cmake
@@ -10,16 +10,14 @@ message(STATUS "Package URL is: ${PACKAGE_URL}")
message(STATUS "Package bug-report address: ${PACKAGE_BUGREPORT}")
message(STATUS "Package install prefix: ${CMAKE_INSTALL_PREFIX}")
-# Pkg-config files configuration
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ouroboros-dev.pc.in"
- "${CMAKE_CURRENT_BINARY_DIR}/ouroboros-dev.pc" @ONLY)
+configure_file("${CMAKE_SOURCE_DIR}/ouroboros-dev.pc.in"
+ "${CMAKE_BINARY_DIR}/ouroboros-dev.pc" @ONLY)
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ouroboros-irm.pc.in"
- "${CMAKE_CURRENT_BINARY_DIR}/ouroboros-irm.pc" @ONLY)
+configure_file("${CMAKE_SOURCE_DIR}/ouroboros-irm.pc.in"
+ "${CMAKE_BINARY_DIR}/ouroboros-irm.pc" @ONLY)
-# CPack packaging configuration
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE_DESCRIPTION}")
-set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
+set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README")
set(CPACK_PACKAGE_VERSION_MAJOR "${PACKAGE_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${PACKAGE_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${PACKAGE_VERSION_PATCH}")
diff --git a/cmake/tests.cmake b/cmake/tests.cmake
index e3857cab..edc2987c 100644
--- a/cmake/tests.cmake
+++ b/cmake/tests.cmake
@@ -1,30 +1,30 @@
include(CTest) # Sets BUILD_TESTING by default to on.
include(utils/TestUtils)
+# Test configuration options
+include(config/tests)
include(utils/DisableTestLogging)
-if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
+if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
set(BUILD_TESTS ON)
-else ()
+else()
set(BUILD_TESTS OFF)
endif()
add_custom_target(build_tests)
-if (BUILD_TESTS)
+if(BUILD_TESTS)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
add_dependencies(check build_tests)
+endif()
- # Add test subdirectories
- add_subdirectory(src/lib/tests)
- add_subdirectory(src/lib/ssm/tests)
- add_subdirectory(src/irmd/oap/tests)
- add_subdirectory(src/ipcpd/unicast/pff/tests)
- add_subdirectory(src/ipcpd/unicast/routing/tests)
- add_subdirectory(src/ipcpd/unicast/dir/tests)
- add_subdirectory(src/irmd/reg/tests)
+# Test subdirectories are added from their parent CMakeLists.txt files
+# via add_subdirectory(tests) - keeping tests with their source code
- # Create coverage target if gcov is available
- include(utils/GenCoverage)
- create_coverage_target()
-endif ()
+# Coverage target setup (called after all targets are defined)
+function(setup_coverage_target)
+ if(BUILD_TESTS)
+ include(utils/GenCoverage)
+ create_coverage_target()
+ endif()
+endfunction()
diff --git a/cmake/tools.cmake b/cmake/tools.cmake
deleted file mode 100644
index de1d374c..00000000
--- a/cmake/tools.cmake
+++ /dev/null
@@ -1,8 +0,0 @@
-include(tools/tools)
-include(tools/irm)
-include(tools/ocbr)
-include(tools/oecho)
-include(tools/obc)
-include(tools/oping)
-include(tools/operf)
-include(tools/ovpn)
diff --git a/cmake/tools/irm.cmake b/cmake/tools/irm.cmake
deleted file mode 100644
index c9090a2c..00000000
--- a/cmake/tools/irm.cmake
+++ /dev/null
@@ -1,33 +0,0 @@
-set(IRM_SOURCE_DIR "${TOOLS_SOURCE_DIR}/irm")
-
-set(IRM_SOURCES
- "${IRM_SOURCE_DIR}/irm.c"
- "${IRM_SOURCE_DIR}/irm_bind_program.c"
- "${IRM_SOURCE_DIR}/irm_bind_process.c"
- "${IRM_SOURCE_DIR}/irm_bind_ipcp.c"
- "${IRM_SOURCE_DIR}/irm_ipcp_create.c"
- "${IRM_SOURCE_DIR}/irm_ipcp_destroy.c"
- "${IRM_SOURCE_DIR}/irm_ipcp_bootstrap.c"
- "${IRM_SOURCE_DIR}/irm_ipcp_enroll.c"
- "${IRM_SOURCE_DIR}/irm_ipcp_list.c"
- "${IRM_SOURCE_DIR}/irm_ipcp_connect.c"
- "${IRM_SOURCE_DIR}/irm_ipcp_disconnect.c"
- "${IRM_SOURCE_DIR}/irm_unbind_program.c"
- "${IRM_SOURCE_DIR}/irm_unbind_process.c"
- "${IRM_SOURCE_DIR}/irm_unbind_ipcp.c"
- "${IRM_SOURCE_DIR}/irm_unbind.c"
- "${IRM_SOURCE_DIR}/irm_bind.c"
- "${IRM_SOURCE_DIR}/irm_ipcp.c"
- "${IRM_SOURCE_DIR}/irm_name.c"
- "${IRM_SOURCE_DIR}/irm_name_create.c"
- "${IRM_SOURCE_DIR}/irm_name_destroy.c"
- "${IRM_SOURCE_DIR}/irm_name_reg.c"
- "${IRM_SOURCE_DIR}/irm_name_unreg.c"
- "${IRM_SOURCE_DIR}/irm_name_list.c"
- "${IRM_SOURCE_DIR}/irm_utils.c"
-)
-
-add_executable(irm ${IRM_SOURCES})
-target_include_directories(irm PRIVATE ${TOOLS_INCLUDE_DIRS})
-target_link_libraries(irm PUBLIC ouroboros-irm)
-install(TARGETS irm RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
diff --git a/cmake/tools/obc.cmake b/cmake/tools/obc.cmake
deleted file mode 100644
index 99e001b6..00000000
--- a/cmake/tools/obc.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-add_executable(obc "${TOOLS_SOURCE_DIR}/obc/obc.c")
-target_include_directories(obc PRIVATE ${TOOLS_INCLUDE_DIRS})
-target_link_libraries(obc PUBLIC ouroboros-dev)
-install(TARGETS obc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/cmake/tools/ocbr.cmake b/cmake/tools/ocbr.cmake
deleted file mode 100644
index bab80da8..00000000
--- a/cmake/tools/ocbr.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-add_executable(ocbr "${TOOLS_SOURCE_DIR}/ocbr/ocbr.c")
-target_include_directories(ocbr PRIVATE ${TOOLS_INCLUDE_DIRS})
-target_link_libraries(ocbr PUBLIC ouroboros-dev)
-install(TARGETS ocbr RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/cmake/tools/oecho.cmake b/cmake/tools/oecho.cmake
deleted file mode 100644
index 73522731..00000000
--- a/cmake/tools/oecho.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-add_executable(oecho "${TOOLS_SOURCE_DIR}/oecho/oecho.c")
-target_include_directories(oecho PRIVATE ${TOOLS_INCLUDE_DIRS})
-target_link_libraries(oecho PUBLIC ouroboros-dev)
-install(TARGETS oecho RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/cmake/tools/operf.cmake b/cmake/tools/operf.cmake
deleted file mode 100644
index f6b2b465..00000000
--- a/cmake/tools/operf.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-add_executable(operf "${TOOLS_SOURCE_DIR}/operf/operf.c")
-target_include_directories(operf PRIVATE ${TOOLS_INCLUDE_DIRS})
-target_link_libraries(operf PUBLIC ouroboros-dev)
-install(TARGETS operf RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/cmake/tools/oping.cmake b/cmake/tools/oping.cmake
deleted file mode 100644
index 6bb18132..00000000
--- a/cmake/tools/oping.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-add_executable(oping "${TOOLS_SOURCE_DIR}/oping/oping.c")
-target_include_directories(oping PRIVATE ${TOOLS_INCLUDE_DIRS})
-target_link_libraries(oping PUBLIC ${LIBM_LIBRARIES} ouroboros-dev)
-install(TARGETS oping RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/cmake/tools/ovpn.cmake b/cmake/tools/ovpn.cmake
deleted file mode 100644
index 331daff9..00000000
--- a/cmake/tools/ovpn.cmake
+++ /dev/null
@@ -1,6 +0,0 @@
-if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
- add_executable(ovpn "${TOOLS_SOURCE_DIR}/ovpn/ovpn.c")
- target_include_directories(ovpn PRIVATE ${TOOLS_INCLUDE_DIRS})
- target_link_libraries(ovpn PUBLIC ouroboros-dev)
- install(TARGETS ovpn RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-endif ()
diff --git a/cmake/tools/tools.cmake b/cmake/tools/tools.cmake
deleted file mode 100644
index 26abdc63..00000000
--- a/cmake/tools/tools.cmake
+++ /dev/null
@@ -1,8 +0,0 @@
-set(TOOLS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src/tools")
-set(TOOLS_BINARY_DIR "${CMAKE_BINARY_DIR}/src/tools")
-
-set(TOOLS_INCLUDE_DIRS
- ${TOOLS_SOURCE_DIR}
- ${CMAKE_SOURCE_DIR}/include
- ${CMAKE_BINARY_DIR}/include
-)
diff --git a/cmake/utils/AddCompileFlags.cmake b/cmake/utils/AddCompileFlags.cmake
index 8f3877d9..b81ccc67 100644
--- a/cmake/utils/AddCompileFlags.cmake
+++ b/cmake/utils/AddCompileFlags.cmake
@@ -1,17 +1,6 @@
-# - MACRO_ADD_COMPILE_FLAGS(<_target> "flags...")
+# - add_compile_flags(<target> <flags>...)
+# Add compile flags to a target using modern CMake
-# Copyright (c) 2006, Oswald Buddenhagen, <ossi@kde.org>
-#
-# Redistribution and use is allowed according to the terms of the BSD license.
-
-macro(add_compile_flags _target _flg)
-
- get_target_property(_flags ${_target} COMPILE_FLAGS)
- if (_flags)
- set(_flags "${_flags} ${_flg}")
- else (_flags)
- set(_flags "${_flg}")
- endif (_flags)
- set_target_properties(${_target} PROPERTIES COMPILE_FLAGS "${_flags}")
-
-endmacro(add_compile_flags)
+macro(add_compile_flags _target)
+ target_compile_options(${_target} PRIVATE ${ARGN})
+endmacro()
diff --git a/cmake/utils/CMakeUninstall.cmake.in b/cmake/utils/CMakeUninstall.cmake.in
index 985b31b2..b8bba5fd 100644
--- a/cmake/utils/CMakeUninstall.cmake.in
+++ b/cmake/utils/CMakeUninstall.cmake.in
@@ -1,29 +1,21 @@
-if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
+if (NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
-endif(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
+endif()
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
-foreach(file ${files})
+foreach (file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
- if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
- if(CMAKE_VERSION VERSION_LESS "3.28.0")
- exec_program(
- "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
- OUTPUT_VARIABLE rm_out
- RETURN_VALUE rm_retval
- )
- else()
- execute_process(
- COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}"
- RESULT_VARIABLE rm_out
- ERROR_VARIABLE rm_retval
- )
- endif ()
- if(NOT "${rm_retval}" STREQUAL "" AND NOT "${rm_retval}" STREQUAL 0)
+ if (IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+ execute_process(
+ COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}"
+ RESULT_VARIABLE rm_out
+ ERROR_VARIABLE rm_retval
+ )
+ if (NOT "${rm_retval}" STREQUAL "" AND NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
- endif(NOT "${rm_retval}" STREQUAL "" AND NOT "${rm_retval}" STREQUAL 0)
- else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+ endif()
+ else()
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
- endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
-endforeach(file)
+ endif()
+endforeach ()
diff --git a/cmake/utils/CompilerUtils.cmake b/cmake/utils/CompilerUtils.cmake
index 7c8b022f..35548f4f 100644
--- a/cmake/utils/CompilerUtils.cmake
+++ b/cmake/utils/CompilerUtils.cmake
@@ -1,13 +1,13 @@
include(CheckCCompilerFlag)
function(test_and_set_c_compiler_flag_global _flag)
-
string(REGEX REPLACE "-" "_" _sflag ${_flag})
- set(CMAKE_REQUIRED_FLAGS ${_flag})
+ string(REGEX REPLACE "=" "_" _sflag ${_sflag})
+ # Use -Werror during test so clang rejects unknown flags
+ set(CMAKE_REQUIRED_FLAGS "-Werror ${_flag}")
check_c_compiler_flag(${_flag} COMPILER_SUPPORTS_FLAG_${_sflag})
if(COMPILER_SUPPORTS_FLAG_${_sflag})
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_flag}" PARENT_SCOPE)
+ add_compile_options(${_flag})
endif()
-
-endfunction(test_and_set_c_compiler_flag_global)
+endfunction()
diff --git a/cmake/utils/DebugTargets.cmake b/cmake/utils/DebugTargets.cmake
new file mode 100644
index 00000000..78899213
--- /dev/null
+++ b/cmake/utils/DebugTargets.cmake
@@ -0,0 +1,16 @@
+# Utility functions for Ouroboros target configuration
+set(OUROBOROS_DEBUG_CONFIGS
+ Debug
+ DebugASan
+ DebugTSan
+ DebugLSan
+ DebugUSan
+ DebugAnalyzer
+)
+
+# Add CONFIG_OUROBOROS_DEBUG definition for debug build types
+function(ouroboros_target_debug_definitions target)
+ list(JOIN OUROBOROS_DEBUG_CONFIGS "," _configs)
+ target_compile_definitions(${target} PRIVATE
+ "$<$<CONFIG:${_configs}>:CONFIG_OUROBOROS_DEBUG>")
+endfunction()
diff --git a/cmake/utils/DisableTestLogging.cmake b/cmake/utils/DisableTestLogging.cmake
index a7e90b38..40c16668 100644
--- a/cmake/utils/DisableTestLogging.cmake
+++ b/cmake/utils/DisableTestLogging.cmake
@@ -1,22 +1,11 @@
-set(DISABLE_TESTS_LOGGING TRUE CACHE BOOL "Disable Ouroboros log output in tests")
-if (DISABLE_TESTS_LOGGING)
- message(STATUS "Ouroboros logging in test output disabled")
-else ()
- message(STATUS "Ouroboros logging in test output enabled")
-endif ()
-
-set(DISABLE_TESTS_CORE_DUMPS TRUE CACHE BOOL "Enable core dumps for tests (useful for debugging)")
-if (DISABLE_TESTS_CORE_DUMPS)
- message(STATUS "Core dumps in tests enabled")
-else ()
- message(STATUS "Core dumps in tests disabled")
-endif ()
+# Macro to apply test logging settings to a target
+# Configuration options are in cmake/config/tests.cmake
macro(disable_test_logging_for_target target)
- if (DISABLE_TESTS_LOGGING)
+ if(DISABLE_TESTS_LOGGING)
target_compile_definitions(${target} PRIVATE OUROBOROS_DISABLE_LOGGING)
- endif ()
- if (DISABLE_TESTS_CORE_DUMPS)
+ endif()
+ if(DISABLE_TESTS_CORE_DUMPS)
target_compile_definitions(${target} PRIVATE DISABLE_TESTS_CORE_DUMPS)
- endif ()
+ endif()
endmacro()
diff --git a/cmake/utils/FindProtobufC.cmake b/cmake/utils/FindProtobufC.cmake
index ff892b5b..4632dfcb 100644
--- a/cmake/utils/FindProtobufC.cmake
+++ b/cmake/utils/FindProtobufC.cmake
@@ -1,22 +1,22 @@
-function(PROTOBUF_GENERATE_C SRCS HDRS)
- if (NOT ARGN)
- message(SEND_ERROR "Error: PROTOBUF_GENERATE_C() called without any proto files")
+function(protobuf_generate_c SRCS HDRS)
+ if(NOT ARGN)
+ message(SEND_ERROR "Error: protobuf_generate_c() called without any proto files")
return()
- endif ()
+ endif()
- if (PROTOBUF_GENERATE_C_APPEND_PATH)
+ if(PROTOBUF_GENERATE_C_APPEND_PATH)
# Create an include path for each file specified
foreach (FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(ABS_PATH ${ABS_FIL} PATH)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
- if (${_contains_already} EQUAL -1)
+ if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
- endif ()
+ endif()
endforeach ()
- else ()
+ else()
set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
- endif ()
+ endif()
set(${SRCS})
set(${HDRS})
@@ -42,33 +42,37 @@ function(PROTOBUF_GENERATE_C SRCS HDRS)
set(${HDRS} ${${HDRS}} PARENT_SCOPE)
endfunction()
-# By default have PROTOBUF_GENERATE_C macro pass -I to protoc
+# By default have protobuf_generate_c function pass -I to protoc
# for each directory where a proto file is referenced.
-if (NOT DEFINED PROTOBUF_GENERATE_C_APPEND_PATH)
+if(NOT DEFINED PROTOBUF_GENERATE_C_APPEND_PATH)
set(PROTOBUF_GENERATE_C_APPEND_PATH TRUE)
-endif ()
+endif()
-# Find library
find_library(PROTOBUF_C_LIBRARY
NAMES libprotobuf-c.so libprotobuf-c libprotobuf-c.dylib
)
mark_as_advanced(PROTOBUF_C_LIBRARY)
-# Find the include directory
find_path(PROTOBUF_C_INCLUDE_DIR
google/protobuf-c/protobuf-c.h
)
mark_as_advanced(PROTOBUF_C_INCLUDE_DIR)
-# Find the protoc-c Executable
find_program(PROTOBUF_PROTOC_C_EXECUTABLE
NAMES protoc protoc-c
DOC "The Google Protocol Buffers C Compiler"
)
mark_as_advanced(PROTOBUF_PROTOC_C_EXECUTABLE)
-find_package(PackageHandleStandardArgs)
+include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ProtobufC DEFAULT_MSG
PROTOBUF_C_LIBRARY PROTOBUF_C_INCLUDE_DIR PROTOBUF_PROTOC_C_EXECUTABLE)
set(PROTOBUF_C_INCLUDE_DIRS ${PROTOBUF_C_INCLUDE_DIR})
+
+if(ProtobufC_FOUND AND NOT TARGET ProtobufC::ProtobufC)
+ add_library(ProtobufC::ProtobufC UNKNOWN IMPORTED)
+ set_target_properties(ProtobufC::ProtobufC PROPERTIES
+ IMPORTED_LOCATION "${PROTOBUF_C_LIBRARY}"
+ INTERFACE_INCLUDE_DIRECTORIES "${PROTOBUF_C_INCLUDE_DIR}")
+endif()
diff --git a/cmake/utils/GenCoverage.cmake b/cmake/utils/GenCoverage.cmake
index 65f5d8ba..0ae11ee8 100644
--- a/cmake/utils/GenCoverage.cmake
+++ b/cmake/utils/GenCoverage.cmake
@@ -57,8 +57,8 @@ function(create_informational_target)
)
endfunction()
-macro(create_coverage_target)
- if(HAVE_GCOV AND ENABLE_COVERAGE)
+function(create_coverage_target)
+ if(HAVE_GCOV AND NOT DISABLE_COVERAGE)
get_html_coverage_commands(HTML_COVERAGE_COMMANDS)
add_custom_target(coverage
@@ -91,4 +91,4 @@ macro(create_coverage_target)
"Coverage not available"
)
endif()
-endmacro()
+endfunction()
diff --git a/cmake/utils/TestUtils.cmake b/cmake/utils/TestUtils.cmake
index e40bdda1..e602690c 100644
--- a/cmake/utils/TestUtils.cmake
+++ b/cmake/utils/TestUtils.cmake
@@ -3,4 +3,36 @@ function(compute_test_prefix)
file(RELATIVE_PATH _prefix "${CMAKE_SOURCE_DIR}/src" "${CMAKE_CURRENT_SOURCE_DIR}")
string(REGEX REPLACE "/tests$" "" _prefix "${_prefix}")
set(TEST_PREFIX "${_prefix}" PARENT_SCOPE)
-endfunction(compute_test_prefix)
+endfunction()
+
+# Register tests from a test executable with the test framework
+# Usage: ouroboros_register_tests(TARGET <target> TESTS <test_list> [ENVIRONMENT <env>])
+# The TESTS argument should be the test list variable created by create_test_sourcelist
+function(ouroboros_register_tests)
+ cmake_parse_arguments(PARSE_ARGV 0 ARG "" "TARGET;ENVIRONMENT" "TESTS")
+
+ if(NOT ARG_TARGET)
+ message(FATAL_ERROR "ouroboros_register_tests: TARGET required")
+ endif()
+
+ if(NOT ARG_TESTS)
+ message(FATAL_ERROR "ouroboros_register_tests: TESTS required")
+ endif()
+
+ # First entry is the test driver, skip it
+ set(_tests ${ARG_TESTS})
+ list(POP_FRONT _tests)
+
+ foreach (test_src ${_tests})
+ get_filename_component(test_name ${test_src} NAME_WE)
+ add_test(${TEST_PREFIX}/${test_name}
+ ${CMAKE_CURRENT_BINARY_DIR}/${ARG_TARGET} ${test_name})
+ # All Ouroboros tests support skip return code
+ set_property(TEST ${TEST_PREFIX}/${test_name} PROPERTY SKIP_RETURN_CODE 1)
+ # Optional environment variables
+ if(ARG_ENVIRONMENT)
+ set_property(TEST ${TEST_PREFIX}/${test_name}
+ PROPERTY ENVIRONMENT "${ARG_ENVIRONMENT}")
+ endif()
+ endforeach ()
+endfunction()
diff --git a/include/ouroboros/flow.h b/include/ouroboros/flow.h
index f9aa0d83..6b3dcde4 100644
--- a/include/ouroboros/flow.h
+++ b/include/ouroboros/flow.h
@@ -46,6 +46,8 @@ struct flow_info {
pid_t n_pid;
pid_t n_1_pid;
+ uid_t uid; /* 0 = privileged (GSPP), > 0 = PUP uid */
+
time_t mpl;
struct qos_spec qs;
diff --git a/include/ouroboros/ipcp-dev.h b/include/ouroboros/ipcp-dev.h
index 118f1101..37c8064f 100644
--- a/include/ouroboros/ipcp-dev.h
+++ b/include/ouroboros/ipcp-dev.h
@@ -47,10 +47,12 @@ int ipcp_flow_write(int fd,
struct ssm_pk_buff * spb);
int np1_flow_read(int fd,
- struct ssm_pk_buff ** spb);
+ struct ssm_pk_buff ** spb,
+ struct ssm_pool * pool);
int np1_flow_write(int fd,
- struct ssm_pk_buff * spb);
+ struct ssm_pk_buff * spb,
+ struct ssm_pool * pool);
int ipcp_flow_dealloc(int fd);
diff --git a/include/ouroboros/local-dev.h b/include/ouroboros/local-dev.h
index da62e31c..cd0298d3 100644
--- a/include/ouroboros/local-dev.h
+++ b/include/ouroboros/local-dev.h
@@ -23,9 +23,11 @@
#ifndef OUROBOROS_LIB_LOCAL_DEV_H
#define OUROBOROS_LIB_LOCAL_DEV_H
-ssize_t local_flow_read(int fd);
+#include <ouroboros/ssm_pool.h>
-int local_flow_write(int fd,
- size_t idx);
+int local_flow_transfer(int src_fd,
+ int dst_fd,
+ struct ssm_pool * src_pool,
+ struct ssm_pool * dst_pool);
#endif /* OUROBOROS_LIB_LOCAL_DEV_H */
diff --git a/include/ouroboros/proc.h b/include/ouroboros/proc.h
index 80c67227..0e27362e 100644
--- a/include/ouroboros/proc.h
+++ b/include/ouroboros/proc.h
@@ -31,8 +31,9 @@
/* Processes */
struct proc_info {
pid_t pid;
- char prog[PROG_NAME_SIZE + 1]; /* program instantiated */
-
+ char prog[PROG_NAME_SIZE + 1];
+ uid_t uid;
+ gid_t gid;
};
/* Programs */
diff --git a/include/ouroboros/serdes-irm.h b/include/ouroboros/serdes-irm.h
index 246db23d..bd04fc57 100644
--- a/include/ouroboros/serdes-irm.h
+++ b/include/ouroboros/serdes-irm.h
@@ -26,6 +26,7 @@
#include <ouroboros/crypt.h>
#include <ouroboros/flow.h>
#include <ouroboros/ipcp.h>
+#include <ouroboros/proc.h>
#include <ouroboros/time.h>
#include <ouroboros/utils.h>
@@ -69,8 +70,8 @@ int ipcp_flow_dealloc__irm_req_ser(buffer_t * buf,
int ipcp_create_r__irm_req_ser(buffer_t * buf,
const struct ipcp_info * ipcp);
-int proc_announce__irm_req_ser(buffer_t * buf,
- const char * prog);
+int proc_announce__irm_req_ser(buffer_t * buf,
+ const struct proc_info * proc);
int proc_exit__irm_req_ser(buffer_t * buf);
diff --git a/include/ouroboros/ssm_pool.h b/include/ouroboros/ssm_pool.h
index 80b22489..4becbdf5 100644
--- a/include/ouroboros/ssm_pool.h
+++ b/include/ouroboros/ssm_pool.h
@@ -32,18 +32,20 @@
struct ssm_pool;
-struct ssm_pool * ssm_pool_create(void);
+/* Pool API: uid = 0 for GSPP (privileged), uid > 0 for PUP (per-user) */
+struct ssm_pool * ssm_pool_create(uid_t uid,
+ gid_t gid);
-struct ssm_pool * ssm_pool_open(void);
+struct ssm_pool * ssm_pool_open(uid_t uid);
void ssm_pool_close(struct ssm_pool * pool);
void ssm_pool_destroy(struct ssm_pool * pool);
-void ssm_pool_purge(void);
-
int ssm_pool_mlock(struct ssm_pool * pool);
+void ssm_pool_gspp_purge(void);
+
/* Alloc count bytes, returns block index, a ptr and pk_buff. */
ssize_t ssm_pool_alloc(struct ssm_pool * pool,
size_t count,
diff --git a/include/ouroboros/utils.h b/include/ouroboros/utils.h
index 5d082d5c..f53361eb 100644
--- a/include/ouroboros/utils.h
+++ b/include/ouroboros/utils.h
@@ -23,9 +23,11 @@
#ifndef OUROBOROS_LIB_UTILS_H
#define OUROBOROS_LIB_UTILS_H
+#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
#include <unistd.h>
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
@@ -54,6 +56,10 @@ char * path_strip(const char * src);
char * trim_whitespace(char * str);
+bool is_ouroboros_member_uid(uid_t uid);
+
+bool is_ouroboros_member(void);
+
/* functions for copying and destroying arguments list */
size_t argvlen(const char ** argv);
diff --git a/src/ipcpd/CMakeLists.txt b/src/ipcpd/CMakeLists.txt
new file mode 100644
index 00000000..609da54a
--- /dev/null
+++ b/src/ipcpd/CMakeLists.txt
@@ -0,0 +1,30 @@
+# IPCP (IPC Process) daemons build configuration
+# Configuration options and validation are in cmake/config/ipcp/*.cmake
+
+# Common sources shared by all IPCPs (absolute paths for subdirectories)
+set(IPCP_SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/ipcp.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/shim-data.c
+)
+
+set(COMMON_SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/common/enroll.c
+)
+
+set(IPCP_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_BINARY_DIR}/include
+)
+
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/config.h" @ONLY)
+
+add_subdirectory(local)
+add_subdirectory(broadcast)
+add_subdirectory(unicast)
+if(HAVE_ETH)
+ add_subdirectory(eth)
+endif()
+add_subdirectory(udp)
diff --git a/src/ipcpd/broadcast/CMakeLists.txt b/src/ipcpd/broadcast/CMakeLists.txt
new file mode 100644
index 00000000..433d9979
--- /dev/null
+++ b/src/ipcpd/broadcast/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Broadcast IPCP build configuration
+
+set(IPCP_BROADCAST_TARGET ipcpd-broadcast)
+
+set(BROADCAST_SOURCES
+ connmgr.c
+ dt.c
+ main.c
+)
+
+add_executable(${IPCP_BROADCAST_TARGET}
+ ${BROADCAST_SOURCES}
+ ${IPCP_SOURCES}
+ ${COMMON_SOURCES}
+)
+
+target_include_directories(${IPCP_BROADCAST_TARGET} PRIVATE ${IPCP_INCLUDE_DIRS})
+target_link_libraries(${IPCP_BROADCAST_TARGET} PRIVATE ouroboros-dev)
+
+ouroboros_target_debug_definitions(${IPCP_BROADCAST_TARGET})
+
+install(TARGETS ${IPCP_BROADCAST_TARGET} RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
diff --git a/src/ipcpd/eth/CMakeLists.txt b/src/ipcpd/eth/CMakeLists.txt
new file mode 100644
index 00000000..e6cc8224
--- /dev/null
+++ b/src/ipcpd/eth/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Ethernet IPCPs build configuration (LLC and DIX)
+# HAVE_ETH detection is in cmake/dependencies.cmake
+
+set(IPCP_ETH_LLC_TARGET ipcpd-eth-llc)
+set(IPCP_ETH_DIX_TARGET ipcpd-eth-dix)
+
+add_executable(${IPCP_ETH_LLC_TARGET} llc.c ${IPCP_SOURCES})
+add_executable(${IPCP_ETH_DIX_TARGET} dix.c ${IPCP_SOURCES})
+
+foreach(target ${IPCP_ETH_LLC_TARGET} ${IPCP_ETH_DIX_TARGET})
+ target_include_directories(${target} PRIVATE ${IPCP_INCLUDE_DIRS})
+ if(HAVE_BPF AND NOT APPLE)
+ target_include_directories(${target} PRIVATE ${BPF_C_INCLUDE_DIR})
+ endif()
+ if(HAVE_NETMAP AND NOT APPLE)
+ target_compile_options(${target} PRIVATE -std=c99)
+ target_include_directories(${target} PRIVATE ${NETMAP_C_INCLUDE_DIR})
+ endif()
+ target_link_libraries(${target} PRIVATE ouroboros-dev)
+ ouroboros_target_debug_definitions(${target})
+endforeach()
+
+install(TARGETS ${IPCP_ETH_LLC_TARGET} ${IPCP_ETH_DIX_TARGET}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
diff --git a/src/ipcpd/eth/eth.c b/src/ipcpd/eth/eth.c
index f36e0b13..9d281297 100644
--- a/src/ipcpd/eth/eth.c
+++ b/src/ipcpd/eth/eth.c
@@ -52,6 +52,7 @@
#include <ouroboros/pthread.h>
#include "ipcp.h"
+#include "np1.h"
#include "shim-data.h"
#include <signal.h>
@@ -990,7 +991,7 @@ static void * eth_ipcp_packet_reader(void * o)
buf = ssm_pk_buff_head(spb);
memcpy(buf, &e_frame->payload, length);
#endif
- if (np1_flow_write(fd, spb) < 0)
+ if (np1_flow_write(fd, spb, NP1_GET_POOL(fd)) < 0)
ipcp_spb_release(spb);
continue;
@@ -1040,7 +1041,7 @@ static void * eth_ipcp_packet_writer(void * o)
if (fqueue_type(fq) != FLOW_PKT)
continue;
- if (np1_flow_read(fd, &spb)) {
+ if (np1_flow_read(fd, &spb, NP1_GET_POOL(fd))) {
log_dbg("Bad read from fd %d.", fd);
continue;
}
diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c
index ebb9b1c5..3ea77da9 100644
--- a/src/ipcpd/ipcp.c
+++ b/src/ipcpd/ipcp.c
@@ -52,6 +52,7 @@
#include <ouroboros/utils.h>
#include "ipcp.h"
+#include "np1.h"
#include <signal.h>
#include <string.h>
@@ -131,6 +132,8 @@ struct {
pthread_t acceptor;
} ipcpd;
+struct np1_state np1;
+
struct cmd {
struct list_head next;
@@ -633,9 +636,11 @@ static void do_flow_alloc(pid_t pid,
uint8_t * dst,
qosspec_t qs,
const buffer_t * data,
+ uid_t uid,
ipcp_msg_t * ret_msg)
{
- int fd;
+ int fd;
+ struct ssm_pool * pool = NULL;
log_info("Allocating flow %d for %d to " HASH_FMT32 ".",
flow_id, pid, HASH_VAL32(dst));
@@ -662,6 +667,17 @@ static void do_flow_alloc(pid_t pid,
return;
}
+ if (uid != 0) {
+ pool = ssm_pool_open(uid);
+ if (pool == NULL) {
+ log_err("Failed to open PUP for uid %d.", uid);
+ ret_msg->result = -ENOMEM;
+ return;
+ }
+ }
+
+ NP1_SET_POOL(fd, pool);
+
ret_msg->result = ipcpd.ops->ipcp_flow_alloc(fd, dst, qs, data);
log_info("Finished allocating flow %d to " HASH_FMT32 ".",
@@ -672,9 +688,11 @@ static void do_flow_alloc(pid_t pid,
static void do_flow_join(pid_t pid,
int flow_id,
const uint8_t * dst,
+ uid_t uid,
ipcp_msg_t * ret_msg)
{
- int fd;
+ int fd;
+ struct ssm_pool * pool = NULL;
log_info("Joining layer " HASH_FMT32 ".", HASH_VAL32(dst));
@@ -699,6 +717,17 @@ static void do_flow_join(pid_t pid,
return;
}
+ if (uid != 0) {
+ pool = ssm_pool_open(uid);
+ if (pool == NULL) {
+ log_err("Failed to open PUP for uid %d.", uid);
+ ret_msg->result = -ENOMEM;
+ return;
+ }
+ }
+
+ NP1_SET_POOL(fd, pool);
+
ret_msg->result = ipcpd.ops->ipcp_flow_join(fd, dst);
log_info("Finished joining layer " HASH_FMT32 ".", HASH_VAL32(dst));
@@ -706,10 +735,12 @@ static void do_flow_join(pid_t pid,
static void do_flow_alloc_resp(int resp,
int flow_id,
+ uid_t uid,
const buffer_t * data,
ipcp_msg_t * ret_msg)
{
- int fd = -1;
+ int fd = -1;
+ struct ssm_pool * pool = NULL;
log_info("Responding %d to alloc on flow_id %d.", resp, flow_id);
@@ -737,6 +768,17 @@ static void do_flow_alloc_resp(int resp,
return;
}
+ if (uid != 0) {
+ pool = ssm_pool_open(uid);
+ if (pool == NULL) {
+ log_err("Failed to open PUP for uid %d.", uid);
+ ret_msg->result = -ENOMEM;
+ return;
+ }
+ }
+
+ NP1_SET_POOL(fd, pool);
+
ret_msg->result = ipcpd.ops->ipcp_flow_alloc_resp(fd, resp, data);
log_info("Finished responding %d to allocation request.",
@@ -857,12 +899,12 @@ static void * mainloop(void * o)
qs = qos_spec_msg_to_s(msg->qosspec);
do_flow_alloc(msg->pid, msg->flow_id,
msg->hash.data, qs,
- &data, &ret_msg);
+ &data, msg->uid, &ret_msg);
break;
case IPCP_MSG_CODE__IPCP_FLOW_JOIN:
assert(msg->hash.len == ipcp_dir_hash_len());
do_flow_join(msg->pid, msg->flow_id,
- msg->hash.data, &ret_msg);
+ msg->hash.data, msg->uid, &ret_msg);
break;
case IPCP_MSG_CODE__IPCP_FLOW_ALLOC_RESP:
assert(msg->pk.len > 0 ? msg->pk.data != NULL
@@ -870,7 +912,7 @@ static void * mainloop(void * o)
data.len = msg->pk.len;
data.data = msg->pk.data;
do_flow_alloc_resp(msg->response, msg->flow_id,
- &data, &ret_msg);
+ msg->uid, &data, &ret_msg);
break;
case IPCP_MSG_CODE__IPCP_FLOW_DEALLOC:
do_flow_dealloc(msg->flow_id, msg->timeo_sec, &ret_msg);
@@ -1035,6 +1077,8 @@ int ipcp_init(int argc,
ipcpd.alloc_id = -1;
+ memset(&np1, 0, sizeof(np1));
+
pthread_condattr_destroy(&cattr);
ipcp_set_state(IPCP_INIT);
diff --git a/src/ipcpd/local/CMakeLists.txt b/src/ipcpd/local/CMakeLists.txt
new file mode 100644
index 00000000..0da4d47a
--- /dev/null
+++ b/src/ipcpd/local/CMakeLists.txt
@@ -0,0 +1,19 @@
+# Local IPCP build configuration
+
+set(IPCP_LOCAL_TARGET ipcpd-local)
+
+add_executable(${IPCP_LOCAL_TARGET}
+ main.c
+ ${IPCP_SOURCES}
+)
+
+target_include_directories(${IPCP_LOCAL_TARGET} PRIVATE ${IPCP_INCLUDE_DIRS})
+target_link_libraries(${IPCP_LOCAL_TARGET} PRIVATE ouroboros-dev)
+
+ouroboros_target_debug_definitions(${IPCP_LOCAL_TARGET})
+
+if(IPCP_LOCAL_POLLING)
+ target_compile_definitions(${IPCP_LOCAL_TARGET} PRIVATE CONFIG_IPCP_LOCAL_POLLING)
+endif()
+
+install(TARGETS ${IPCP_LOCAL_TARGET} RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c
index e0f3cc5a..5372197f 100644
--- a/src/ipcpd/local/main.c
+++ b/src/ipcpd/local/main.c
@@ -40,6 +40,7 @@
#include <ouroboros/local-dev.h>
#include "ipcp.h"
+#include "np1.h"
#include "shim-data.h"
#include <string.h>
@@ -103,32 +104,41 @@ static void local_data_fini(void){
static void * local_ipcp_packet_loop(void * o)
{
+ int src_fd;
+ int dst_fd;
+ struct timespec * timeout;
+#ifdef CONFIG_IPCP_LOCAL_POLLING
+ struct timespec ts_poll = {0, 0};
+#endif
(void) o;
ipcp_lock_to_core();
- while (true) {
- int fd;
- ssize_t idx;
+#ifdef CONFIG_IPCP_LOCAL_POLLING
+ timeout = &ts_poll; /* Spin poll with zero timeout */
+#else
+ timeout = NULL; /* Block until event */
+#endif
- fevent(local_data.flows, local_data.fq, NULL);
+ while (true) {
+ fevent(local_data.flows, local_data.fq, timeout);
- while ((fd = fqueue_next(local_data.fq)) >= 0) {
+ while ((src_fd = fqueue_next(local_data.fq)) >= 0) {
if (fqueue_type(local_data.fq) != FLOW_PKT)
continue;
- idx = local_flow_read(fd);
- if (idx < 0)
- continue;
-
pthread_rwlock_rdlock(&local_data.lock);
- fd = local_data.in_out[fd];
+ dst_fd = local_data.in_out[src_fd];
pthread_rwlock_unlock(&local_data.lock);
- if (fd != -1)
- local_flow_write(fd, idx);
+ if (dst_fd == -1)
+ continue;
+
+ local_flow_transfer(src_fd, dst_fd,
+ NP1_GET_POOL(src_fd),
+ NP1_GET_POOL(dst_fd));
}
}
diff --git a/src/ipcpd/np1.h b/src/ipcpd/np1.h
new file mode 100644
index 00000000..a3f21200
--- /dev/null
+++ b/src/ipcpd/np1.h
@@ -0,0 +1,41 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2024
+ *
+ * N+1 flow pool tracking for IPCPs
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., http://www.fsf.org/about/contact/.
+ */
+
+#ifndef OUROBOROS_IPCPD_NP1_H
+#define OUROBOROS_IPCPD_NP1_H
+
+#include "config.h"
+
+#include <ouroboros/ssm_pool.h>
+
+#define NP1_LOAD(ptr) (__atomic_load_n((ptr), __ATOMIC_ACQUIRE))
+#define NP1_STORE(ptr, v) (__atomic_store_n((ptr), (v), __ATOMIC_RELEASE))
+#define NP1_GET_POOL(fd) (NP1_LOAD(&np1.pool[(fd)]))
+#define NP1_SET_POOL(fd, p) (NP1_STORE(&np1.pool[(fd)], (p)))
+
+struct np1_state {
+ struct ssm_pool * pool[SYS_MAX_FLOWS];
+};
+
+extern struct np1_state np1;
+
+#endif /* OUROBOROS_IPCPD_NP1_H */
diff --git a/src/ipcpd/udp/CMakeLists.txt b/src/ipcpd/udp/CMakeLists.txt
new file mode 100644
index 00000000..159e9bf5
--- /dev/null
+++ b/src/ipcpd/udp/CMakeLists.txt
@@ -0,0 +1,17 @@
+# UDP IPCPs build configuration (UDP4 and UDP6)
+# DDNS detection is in cmake/dependencies/udp/ddns.cmake
+
+set(IPCP_UDP4_TARGET ipcpd-udp4)
+set(IPCP_UDP6_TARGET ipcpd-udp6)
+
+add_executable(${IPCP_UDP4_TARGET} udp4.c ${IPCP_SOURCES})
+add_executable(${IPCP_UDP6_TARGET} udp6.c ${IPCP_SOURCES})
+
+foreach(target ${IPCP_UDP4_TARGET} ${IPCP_UDP6_TARGET})
+ target_include_directories(${target} PRIVATE ${IPCP_INCLUDE_DIRS})
+ target_link_libraries(${target} PRIVATE ouroboros-dev)
+ ouroboros_target_debug_definitions(${target})
+endforeach()
+
+install(TARGETS ${IPCP_UDP4_TARGET} ${IPCP_UDP6_TARGET}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
diff --git a/src/ipcpd/udp/udp.c b/src/ipcpd/udp/udp.c
index 5e29cb52..5803e674 100644
--- a/src/ipcpd/udp/udp.c
+++ b/src/ipcpd/udp/udp.c
@@ -34,6 +34,7 @@
#include <ouroboros/pthread.h>
#include "ipcp.h"
+#include "np1.h"
#include "shim-data.h"
#include <string.h>
@@ -492,7 +493,7 @@ static void * udp_ipcp_packet_reader(void * o)
head = ssm_pk_buff_head(spb);
memcpy(head, data, n);
- if (np1_flow_write(eid, spb) < 0)
+ if (np1_flow_write(eid, spb, NP1_GET_POOL(eid)) < 0)
ipcp_spb_release(spb);
}
@@ -536,7 +537,7 @@ static void * udp_ipcp_packet_writer(void * o)
if (fqueue_type(fq) != FLOW_PKT)
continue;
- if (np1_flow_read(fd, &spb)) {
+ if (np1_flow_read(fd, &spb, NP1_GET_POOL(fd))) {
log_dbg("Bad read from fd %d.", fd);
continue;
}
diff --git a/src/ipcpd/unicast/CMakeLists.txt b/src/ipcpd/unicast/CMakeLists.txt
new file mode 100644
index 00000000..1e095f8b
--- /dev/null
+++ b/src/ipcpd/unicast/CMakeLists.txt
@@ -0,0 +1,51 @@
+# Unicast IPCP build configuration
+
+set(IPCP_UNICAST_TARGET ipcpd-unicast)
+
+protobuf_generate_c(DHT_PROTO_SRCS DHT_PROTO_HDRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/dir/dht.proto")
+
+set(UNICAST_SOURCES
+ addr-auth.c
+ ca.c
+ connmgr.c
+ dir.c
+ dt.c
+ fa.c
+ main.c
+ pff.c
+ routing.c
+ psched.c
+ addr-auth/flat.c
+ ca/mb-ecn.c
+ ca/nop.c
+ dir/dht.c
+ pff/simple.c
+ pff/alternate.c
+ pff/multipath.c
+ pff/pft.c
+ routing/link-state.c
+ routing/graph.c
+)
+
+add_executable(${IPCP_UNICAST_TARGET}
+ ${UNICAST_SOURCES}
+ ${IPCP_SOURCES}
+ ${COMMON_SOURCES}
+ ${DHT_PROTO_SRCS}
+)
+
+target_include_directories(${IPCP_UNICAST_TARGET} PRIVATE ${IPCP_INCLUDE_DIRS})
+target_include_directories(${IPCP_UNICAST_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
+target_include_directories(${IPCP_UNICAST_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
+target_link_libraries(${IPCP_UNICAST_TARGET} PRIVATE ouroboros-dev)
+
+ouroboros_target_debug_definitions(${IPCP_UNICAST_TARGET})
+
+install(TARGETS ${IPCP_UNICAST_TARGET} RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
+
+if(BUILD_TESTS)
+ add_subdirectory(dir/tests)
+ add_subdirectory(pff/tests)
+ add_subdirectory(routing/tests)
+endif()
diff --git a/src/ipcpd/unicast/dir/tests/CMakeLists.txt b/src/ipcpd/unicast/dir/tests/CMakeLists.txt
index dd15d4d8..eded823f 100644
--- a/src/ipcpd/unicast/dir/tests/CMakeLists.txt
+++ b/src/ipcpd/unicast/dir/tests/CMakeLists.txt
@@ -3,21 +3,6 @@ get_filename_component(CURRENT_SOURCE_PARENT_DIR
get_filename_component(CURRENT_BINARY_PARENT_DIR
${CMAKE_CURRENT_BINARY_DIR} DIRECTORY)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-
-include_directories(${CURRENT_SOURCE_PARENT_DIR})
-include_directories(${CURRENT_BINARY_PARENT_DIR})
-
-include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories(${CMAKE_BINARY_DIR}/include)
-
-# Add includes for ipcp and unicast module files
-include_directories(${CMAKE_SOURCE_DIR}/src/ipcpd)
-include_directories(${CMAKE_BINARY_DIR}/src/ipcpd)
-include_directories(${CMAKE_SOURCE_DIR}/src/ipcpd/unicast)
-include_directories(${CMAKE_BINARY_DIR}/src/ipcpd/unicast)
-
get_filename_component(PARENT_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
get_filename_component(PARENT_DIR ${PARENT_PATH} NAME)
@@ -26,25 +11,28 @@ compute_test_prefix()
create_test_sourcelist(${PARENT_DIR}_tests test_suite.c
# Add new tests here
dht_test.c
- )
+)
protobuf_generate_c(DHT_PROTO_SRCS KAD_PROTO_HDRS ${CURRENT_SOURCE_PARENT_DIR}/dht.proto)
add_executable(${PARENT_DIR}_test ${${PARENT_DIR}_tests}
${DHT_PROTO_SRCS})
+target_include_directories(${PARENT_DIR}_test PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CURRENT_SOURCE_PARENT_DIR}
+ ${CURRENT_BINARY_PARENT_DIR}
+ ${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_BINARY_DIR}/include
+ ${CMAKE_SOURCE_DIR}/src/ipcpd
+ ${CMAKE_BINARY_DIR}/src/ipcpd
+ ${CMAKE_SOURCE_DIR}/src/ipcpd/unicast
+ ${CMAKE_BINARY_DIR}/src/ipcpd/unicast
+)
+
disable_test_logging_for_target(${PARENT_DIR}_test)
target_link_libraries(${PARENT_DIR}_test ouroboros-common)
add_dependencies(build_tests ${PARENT_DIR}_test)
-set(tests_to_run ${${PARENT_DIR}_tests})
-if(CMAKE_VERSION VERSION_LESS "3.29.0")
- remove(tests_to_run test_suite.c)
-else ()
- list(POP_FRONT tests_to_run)
-endif()
-
-foreach (test ${tests_to_run})
- get_filename_component(test_name ${test} NAME_WE)
- add_test(${TEST_PREFIX}/${test_name} ${C_TEST_PATH}/${PARENT_DIR}_test ${test_name})
-endforeach (test)
+ouroboros_register_tests(TARGET ${PARENT_DIR}_test TESTS ${${PARENT_DIR}_tests})
diff --git a/src/ipcpd/unicast/fa.c b/src/ipcpd/unicast/fa.c
index 06e4b043..07f5b46c 100644
--- a/src/ipcpd/unicast/fa.c
+++ b/src/ipcpd/unicast/fa.c
@@ -48,6 +48,7 @@
#include "ipcp.h"
#include "dt.h"
#include "ca.h"
+#include "np1.h"
#include <inttypes.h>
#include <stdlib.h>
@@ -687,6 +688,12 @@ void fa_fini(void)
pthread_rwlock_destroy(&fa.flows_lock);
}
+static int np1_flow_read_fa(int fd,
+ struct ssm_pk_buff ** spb)
+{
+ return np1_flow_read(fd, spb, NP1_GET_POOL(fd));
+}
+
int fa_start(void)
{
#ifndef BUILD_CONTAINER
@@ -695,7 +702,7 @@ int fa_start(void)
int max;
#endif
- fa.psched = psched_create(packet_handler, np1_flow_read);
+ fa.psched = psched_create(packet_handler, np1_flow_read_fa);
if (fa.psched == NULL) {
log_err("Failed to start packet scheduler.");
goto fail_psched;
@@ -963,7 +970,7 @@ void fa_np1_rcv(uint64_t eid,
pthread_rwlock_unlock(&fa.flows_lock);
- if (ipcp_flow_write(fd, spb) < 0) {
+ if (np1_flow_write(fd, spb, NP1_GET_POOL(fd)) < 0) {
log_dbg("Failed to write to flow %d.", fd);
ipcp_spb_release(spb);
#ifdef IPCP_FLOW_STATS
diff --git a/src/ipcpd/unicast/pff/tests/CMakeLists.txt b/src/ipcpd/unicast/pff/tests/CMakeLists.txt
index ccca26a0..8c0e3d51 100644
--- a/src/ipcpd/unicast/pff/tests/CMakeLists.txt
+++ b/src/ipcpd/unicast/pff/tests/CMakeLists.txt
@@ -3,19 +3,6 @@ get_filename_component(CURRENT_SOURCE_PARENT_DIR
get_filename_component(CURRENT_BINARY_PARENT_DIR
${CMAKE_CURRENT_BINARY_DIR} DIRECTORY)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-
-include_directories(${CURRENT_SOURCE_PARENT_DIR})
-include_directories(${CURRENT_BINARY_PARENT_DIR})
-
-include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories(${CMAKE_BINARY_DIR}/include)
-
-# Add includes for ipcp module files
-include_directories(${CMAKE_SOURCE_DIR}/src/ipcpd)
-include_directories(${CMAKE_BINARY_DIR}/src/ipcpd)
-
get_filename_component(PARENT_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
get_filename_component(PARENT_DIR ${PARENT_PATH} NAME)
@@ -27,19 +14,21 @@ create_test_sourcelist(${PARENT_DIR}_tests test_suite.c
)
add_executable(${PARENT_DIR}_test ${${PARENT_DIR}_tests})
+
+target_include_directories(${PARENT_DIR}_test PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CURRENT_SOURCE_PARENT_DIR}
+ ${CURRENT_BINARY_PARENT_DIR}
+ ${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_BINARY_DIR}/include
+ ${CMAKE_SOURCE_DIR}/src/ipcpd
+ ${CMAKE_BINARY_DIR}/src/ipcpd
+)
+
disable_test_logging_for_target(${PARENT_DIR}_test)
-target_link_libraries(${PARENT_DIR}_test ouroboros-common)
+target_link_libraries(${PARENT_DIR}_test PRIVATE ouroboros-common)
add_dependencies(build_tests ${PARENT_DIR}_test)
-set(tests_to_run ${${PARENT_DIR}_tests})
-if(CMAKE_VERSION VERSION_LESS "3.29.0")
- remove(tests_to_run test_suite.c)
-else ()
- list(POP_FRONT tests_to_run)
-endif()
-
-foreach (test ${tests_to_run})
- get_filename_component(test_name ${test} NAME_WE)
- add_test(${TEST_PREFIX}/${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${PARENT_DIR}_test ${test_name})
-endforeach (test)
+ouroboros_register_tests(TARGET ${PARENT_DIR}_test TESTS ${${PARENT_DIR}_tests})
diff --git a/src/ipcpd/unicast/routing/tests/CMakeLists.txt b/src/ipcpd/unicast/routing/tests/CMakeLists.txt
index f97d03bb..be2de72c 100644
--- a/src/ipcpd/unicast/routing/tests/CMakeLists.txt
+++ b/src/ipcpd/unicast/routing/tests/CMakeLists.txt
@@ -3,18 +3,6 @@ get_filename_component(CURRENT_SOURCE_PARENT_DIR
get_filename_component(CURRENT_BINARY_PARENT_DIR
${CMAKE_CURRENT_BINARY_DIR} DIRECTORY)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-
-include_directories(${CURRENT_SOURCE_PARENT_DIR})
-include_directories(${CURRENT_BINARY_PARENT_DIR})
-
-include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories(${CMAKE_BINARY_DIR}/include)
-
-include_directories(${CMAKE_SOURCE_DIR}/src/ipcpd)
-include_directories(${CMAKE_BINARY_DIR}/src/ipcpd)
-
get_filename_component(PARENT_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
get_filename_component(PARENT_DIR ${PARENT_PATH} NAME)
@@ -27,19 +15,20 @@ create_test_sourcelist(${PARENT_DIR}_tests test_suite.c
add_executable(${PARENT_DIR}_test ${${PARENT_DIR}_tests})
+target_include_directories(${PARENT_DIR}_test PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CURRENT_SOURCE_PARENT_DIR}
+ ${CURRENT_BINARY_PARENT_DIR}
+ ${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_BINARY_DIR}/include
+ ${CMAKE_SOURCE_DIR}/src/ipcpd
+ ${CMAKE_BINARY_DIR}/src/ipcpd
+)
+
disable_test_logging_for_target(${PARENT_DIR}_test)
-target_link_libraries(${PARENT_DIR}_test ouroboros-common)
+target_link_libraries(${PARENT_DIR}_test PRIVATE ouroboros-common)
add_dependencies(build_tests ${PARENT_DIR}_test)
-set(tests_to_run ${${PARENT_DIR}_tests})
-if(CMAKE_VERSION VERSION_LESS "3.29.0")
- remove(tests_to_run test_suite.c)
-else ()
- list(POP_FRONT tests_to_run)
-endif()
-
-foreach (test ${tests_to_run})
- get_filename_component(test_name ${test} NAME_WE)
- add_test(${TEST_PREFIX}/${test_name} ${C_TEST_PATH}/${PARENT_DIR}_test ${test_name})
-endforeach (test)
+ouroboros_register_tests(TARGET ${PARENT_DIR}_test TESTS ${${PARENT_DIR}_tests})
diff --git a/src/irmd/CMakeLists.txt b/src/irmd/CMakeLists.txt
new file mode 100644
index 00000000..d65635af
--- /dev/null
+++ b/src/irmd/CMakeLists.txt
@@ -0,0 +1,65 @@
+# IRMd (IPC Resource Manager daemon) build configuration
+# Configuration options are in cmake/config/global.cmake and cmake/config/irmd.cmake
+
+# Generate and install configuration files if TOML support available
+# HAVE_TOML is set in cmake/dependencies/irmd/libtoml.cmake
+if(HAVE_TOML)
+ set(INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
+ configure_file("${CMAKE_SOURCE_DIR}/irmd.conf.in"
+ "${CMAKE_BINARY_DIR}/${OUROBOROS_CONFIG_FILE}.example" @ONLY)
+ configure_file("${CMAKE_SOURCE_DIR}/enc.conf.in"
+ "${CMAKE_BINARY_DIR}/enc.conf.example" @ONLY)
+ install(FILES "${CMAKE_BINARY_DIR}/${OUROBOROS_CONFIG_FILE}.example"
+ DESTINATION "${OUROBOROS_CONFIG_DIR}")
+ install(FILES "${CMAKE_BINARY_DIR}/enc.conf.example"
+ DESTINATION "${OUROBOROS_CONFIG_DIR}")
+ install(CODE "
+ if(NOT EXISTS \"${OUROBOROS_CONFIG_DIR}/${OUROBOROS_CONFIG_FILE}\")
+ file(WRITE \"${OUROBOROS_CONFIG_DIR}/${OUROBOROS_CONFIG_FILE}\" \"\")
+ endif()
+ ")
+ unset(INSTALL_DIR)
+endif()
+
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/config.h" @ONLY)
+
+set(IRMD_SOURCES
+ ipcp.c
+ configfile.c
+ main.c
+ oap/io.c
+ oap/hdr.c
+ oap/auth.c
+ oap/srv.c
+ oap/cli.c
+ reg/flow.c
+ reg/ipcp.c
+ reg/pool.c
+ reg/proc.c
+ reg/prog.c
+ reg/name.c
+ reg/reg.c
+)
+
+add_executable(irmd ${IRMD_SOURCES})
+
+target_include_directories(irmd PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_BINARY_DIR}/include)
+
+target_link_libraries(irmd PRIVATE ouroboros-common)
+if(HAVE_TOML)
+ target_link_libraries(irmd PRIVATE toml::toml)
+endif()
+
+ouroboros_target_debug_definitions(irmd)
+
+install(TARGETS irmd RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
+
+if(BUILD_TESTS)
+ add_subdirectory(oap/tests)
+ add_subdirectory(reg/tests)
+endif()
diff --git a/src/irmd/config.h.in b/src/irmd/config.h.in
index 43d7f4ee..e1072193 100644
--- a/src/irmd/config.h.in
+++ b/src/irmd/config.h.in
@@ -53,6 +53,8 @@
#define IRMD_MIN_THREADS @IRMD_MIN_THREADS@
#define IRMD_ADD_THREADS @IRMD_ADD_THREADS@
+#define SSM_PID_GSPP 0
+
#cmakedefine HAVE_FUSE
#ifdef HAVE_FUSE
#define FUSE_PREFIX "@FUSE_PREFIX@"
diff --git a/src/irmd/ipcp.c b/src/irmd/ipcp.c
index 6226aeda..d261fc57 100644
--- a/src/irmd/ipcp.c
+++ b/src/irmd/ipcp.c
@@ -421,6 +421,8 @@ int ipcp_flow_join(const struct flow_info * flow,
msg.flow_id = flow->id;
msg.has_pid = true;
msg.pid = flow->n_pid;
+ msg.has_uid = true;
+ msg.uid = flow->uid;
msg.has_hash = true;
msg.hash.data = (uint8_t *) dst.data;
msg.hash.len = dst.len;
@@ -455,6 +457,8 @@ int ipcp_flow_alloc(const struct flow_info * flow,
msg.flow_id = flow->id;
msg.has_pid = true;
msg.pid = flow->n_pid;
+ msg.has_uid = true;
+ msg.uid = flow->uid;
msg.qosspec = qos_spec_s_to_msg(&flow->qs);
msg.has_hash = true;
msg.hash.data = (uint8_t *) dst.data;
@@ -495,6 +499,8 @@ int ipcp_flow_alloc_resp(const struct flow_info * flow,
msg.flow_id = flow->id;
msg.has_pid = true;
msg.pid = flow->n_pid;
+ msg.has_uid = true;
+ msg.uid = flow->uid;
msg.has_response = true;
msg.response = response;
msg.has_pk = response == 0;
diff --git a/src/irmd/main.c b/src/irmd/main.c
index 5b787a24..ccb16017 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -22,6 +22,7 @@
#if defined(__linux__) || defined(__CYGWIN__)
#define _DEFAULT_SOURCE
+#define _GNU_SOURCE
#else
#define _POSIX_C_SOURCE 200809L
#endif
@@ -39,6 +40,7 @@
#include <ouroboros/list.h>
#include <ouroboros/lockfile.h>
#include <ouroboros/logs.h>
+#include <ouroboros/protobuf.h>
#include <ouroboros/pthread.h>
#include <ouroboros/random.h>
#include <ouroboros/rib.h>
@@ -56,6 +58,8 @@
#include "configfile.h"
#include <dirent.h>
+#include <grp.h>
+#include <pwd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
@@ -770,18 +774,47 @@ static int name_unreg(const char * name,
return -1;
}
+static int get_peer_ids(int fd,
+ uid_t * uid,
+ gid_t * gid)
+{
+#if defined(__linux__)
+ struct ucred ucred;
+ socklen_t len;
+
+ len = sizeof(ucred);
+
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0)
+ goto fail;
+
+ *uid = ucred.uid;
+ *gid = ucred.gid;
+#else
+ if (getpeereid(fd, uid, gid) < 0)
+ goto fail;
+#endif
+ return 0;
+ fail:
+ return -1;
+}
+
static int proc_announce(const struct proc_info * info)
{
+ if (reg_prepare_pool(info->uid, info->gid) < 0) {
+ log_err("Failed to prepare pool for uid %d.", info->uid);
+ goto fail;
+ }
+
if (reg_create_proc(info) < 0) {
log_err("Failed to add process %d.", info->pid);
- goto fail_proc;
+ goto fail;
}
log_info("Process added: %d (%s).", info->pid, info->prog);
return 0;
- fail_proc:
+ fail:
return -1;
}
@@ -868,6 +901,8 @@ static int flow_accept(struct flow_info * flow,
log_dbg("IPCP %d accepting flow %d for %s.",
flow->n_pid, flow->id, name);
+ flow->uid = reg_get_proc_uid(flow->n_pid);
+
err = oap_srv_process(&info, req_hdr, &resp_hdr, data, sk);
if (err < 0) {
log_err("OAP processing failed for %s.", name);
@@ -879,7 +914,8 @@ static int flow_accept(struct flow_info * flow,
goto fail_resp;
}
- log_info("Flow %d accepted by %d for %s.", flow->id, flow->n_pid, name);
+ log_info("Flow %d accepted by %d for %s (uid %d).",
+ flow->id, flow->n_pid, name, flow->uid);
freebuf(req_hdr);
freebuf(resp_hdr);
@@ -911,14 +947,17 @@ static int flow_join(struct flow_info * flow,
buffer_t pbuf = BUF_INIT; /* nothing to piggyback */
int err;
- log_info("Allocating flow for %d to %s.", flow->n_pid, dst);
-
if (reg_create_flow(flow) < 0) {
log_err("Failed to create flow.");
err = -EBADF;
goto fail_flow;
}
+ flow->uid = reg_get_proc_uid(flow->n_pid);
+
+ log_info("Allocating flow for %d to %s (uid %d).",
+ flow->n_pid, dst, flow->uid);
+
strcpy(layer.name, dst);
if (reg_get_ipcp_by_layer(&ipcp, &layer) < 0) {
log_err("Failed to get IPCP for layer %s.", dst);
@@ -1053,8 +1092,6 @@ static int flow_alloc(const char * dst,
/* piggyback of user data not yet implemented */
assert(data != NULL && BUF_IS_EMPTY(data));
- log_info("Allocating flow for %d to %s.", flow->n_pid, dst);
-
/* Look up name_info for dst */
if (reg_get_name_info(dst, &info) < 0) {
log_err("Failed to get name info for %s.", dst);
@@ -1068,6 +1105,11 @@ static int flow_alloc(const char * dst,
goto fail_flow;
}
+ flow->uid = reg_get_proc_uid(flow->n_pid);
+
+ log_info("Allocating flow for %d to %s (uid %d).",
+ flow->n_pid, dst, flow->uid);
+
if (get_ipcp_by_dst(dst, &flow->n_1_pid, &hash) < 0) {
log_err("Failed to find IPCP for %s.", dst);
err = -EIPCP;
@@ -1332,7 +1374,8 @@ static void __cleanup_irm_msg(void * o)
irm_msg__free_unpacked((irm_msg_t *) o, NULL);
}
-static irm_msg_t * do_command_msg(irm_msg_t * msg)
+static irm_msg_t * do_command_msg(irm_msg_t * msg,
+ int fd)
{
struct ipcp_config conf;
struct ipcp_info ipcp;
@@ -1413,7 +1456,11 @@ static irm_msg_t * do_command_msg(irm_msg_t * msg)
case IRM_MSG_CODE__IRM_PROC_ANNOUNCE:
proc.pid = msg->pid;
strcpy(proc.prog, msg->prog);
- res = proc_announce(&proc);
+ res = get_peer_ids(fd, &proc.uid, &proc.gid);
+ if (res < 0)
+ log_err("Failed to get UID/GID for pid %d.", msg->pid);
+ else
+ res = proc_announce(&proc);
break;
case IRM_MSG_CODE__IRM_PROC_EXIT:
res = proc_exit(msg->pid);
@@ -1598,7 +1645,7 @@ static void * mainloop(void * o)
pthread_cleanup_push(__cleanup_close_ptr, &sfd);
pthread_cleanup_push(__cleanup_irm_msg, msg);
- ret_msg = do_command_msg(msg);
+ ret_msg = do_command_msg(msg, sfd);
pthread_cleanup_pop(true);
pthread_cleanup_pop(false);
@@ -1691,7 +1738,7 @@ static void destroy_mount(char * mnt)
static int ouroboros_reset(void)
{
- ssm_pool_purge();
+ ssm_pool_gspp_purge();
lockfile_destroy(irmd.lf);
return 0;
@@ -1813,6 +1860,8 @@ static int irm_load_store(char * dpath)
static int irm_init(void)
{
struct stat st;
+ struct group * grp;
+ gid_t gid;
pthread_condattr_t cattr;
#ifdef HAVE_FUSE
mode_t mask;
@@ -1898,8 +1947,17 @@ static int irm_init(void)
goto fail_sock_path;
}
- if ((irmd.gspp = ssm_pool_create()) == NULL) {
- log_err("Failed to create pool.");
+ grp = getgrnam("ouroboros");
+ if (grp == NULL) {
+ log_warn("ouroboros group not found, using gid %d.", getgid());
+ gid = getgid();
+ } else {
+ gid = grp->gr_gid;
+ }
+
+ irmd.gspp = ssm_pool_create(getuid(), gid);
+ if (irmd.gspp == NULL) {
+ log_err("Failed to create GSPP.");
goto fail_pool;
}
@@ -2006,8 +2064,7 @@ static void irm_fini(void)
if (unlink(IRM_SOCK_PATH))
log_dbg("Failed to unlink %s.", IRM_SOCK_PATH);
- if (irmd.gspp != NULL)
- ssm_pool_destroy(irmd.gspp);
+ ssm_pool_destroy(irmd.gspp);
if (irmd.lf != NULL)
lockfile_destroy(irmd.lf);
diff --git a/src/irmd/oap/tests/CMakeLists.txt b/src/irmd/oap/tests/CMakeLists.txt
index 2e8f1319..2bf23821 100644
--- a/src/irmd/oap/tests/CMakeLists.txt
+++ b/src/irmd/oap/tests/CMakeLists.txt
@@ -1,5 +1,5 @@
-get_filename_component(tmp ".." ABSOLUTE)
-get_filename_component(src_folder "${tmp}" NAME)
+get_filename_component(PARENT_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
+get_filename_component(PARENT_DIR ${PARENT_PATH} NAME)
get_filename_component(OAP_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" DIRECTORY)
get_filename_component(OAP_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}" DIRECTORY)
@@ -8,12 +8,12 @@ get_filename_component(IRMD_BINARY_DIR "${OAP_BINARY_DIR}" DIRECTORY)
compute_test_prefix()
-create_test_sourcelist(${src_folder}_tests test_suite.c
+create_test_sourcelist(${PARENT_DIR}_tests test_suite.c
# Add new tests here
oap_test.c
)
-create_test_sourcelist(${src_folder}_pqc_tests test_suite_pqc.c
+create_test_sourcelist(${PARENT_DIR}_pqc_tests test_suite_pqc.c
# PQC-specific tests
oap_test_pqc.c
)
@@ -29,59 +29,36 @@ set(OAP_TEST_SOURCES
)
# Regular test executable (ECDSA)
-add_executable(${src_folder}_test ${${src_folder}_tests} ${OAP_TEST_SOURCES})
+add_executable(${PARENT_DIR}_test ${${PARENT_DIR}_tests} ${OAP_TEST_SOURCES})
set_source_files_properties(${OAP_TEST_SOURCES}
PROPERTIES COMPILE_DEFINITIONS "OAP_TEST_MODE"
)
-disable_test_logging_for_target(${src_folder}_test)
-target_link_libraries(${src_folder}_test ouroboros-irm)
-target_include_directories(${src_folder}_test PRIVATE
+disable_test_logging_for_target(${PARENT_DIR}_test)
+target_link_libraries(${PARENT_DIR}_test ouroboros-irm)
+target_include_directories(${PARENT_DIR}_test PRIVATE
${IRMD_SOURCE_DIR}
${IRMD_BINARY_DIR}
)
# PQC test executable (ML-DSA)
-add_executable(${src_folder}_pqc_test ${${src_folder}_pqc_tests} ${OAP_TEST_SOURCES})
+add_executable(${PARENT_DIR}_pqc_test ${${PARENT_DIR}_pqc_tests} ${OAP_TEST_SOURCES})
set_source_files_properties(${OAP_TEST_SOURCES}
- TARGET_DIRECTORY ${src_folder}_pqc_test
+ TARGET_DIRECTORY ${PARENT_DIR}_pqc_test
PROPERTIES COMPILE_DEFINITIONS "OAP_TEST_MODE"
)
-disable_test_logging_for_target(${src_folder}_pqc_test)
-target_link_libraries(${src_folder}_pqc_test ouroboros-irm)
-target_include_directories(${src_folder}_pqc_test PRIVATE
+disable_test_logging_for_target(${PARENT_DIR}_pqc_test)
+target_link_libraries(${PARENT_DIR}_pqc_test ouroboros-irm)
+target_include_directories(${PARENT_DIR}_pqc_test PRIVATE
${IRMD_SOURCE_DIR}
${IRMD_BINARY_DIR}
)
-add_dependencies(build_tests ${src_folder}_test ${src_folder}_pqc_test)
+add_dependencies(build_tests ${PARENT_DIR}_test ${PARENT_DIR}_pqc_test)
# Regular tests
-set(tests_to_run ${${src_folder}_tests})
-if(CMAKE_VERSION VERSION_LESS "3.29.0")
- remove(tests_to_run test_suite.c)
-else ()
- list(POP_FRONT tests_to_run)
-endif()
-
-foreach(test ${tests_to_run})
- get_filename_component(test_name ${test} NAME_WE)
- add_test(${TEST_PREFIX}/${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${src_folder}_test ${test_name})
-endforeach(test)
+ouroboros_register_tests(TARGET ${PARENT_DIR}_test TESTS ${${PARENT_DIR}_tests})
# PQC tests
-set(pqc_tests_to_run ${${src_folder}_pqc_tests})
-if(CMAKE_VERSION VERSION_LESS "3.29.0")
- remove(pqc_tests_to_run test_suite_pqc.c)
-else ()
- list(POP_FRONT pqc_tests_to_run)
-endif()
-
-foreach(test ${pqc_tests_to_run})
- get_filename_component(test_name ${test} NAME_WE)
- add_test(${TEST_PREFIX}/${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${src_folder}_pqc_test ${test_name})
-endforeach(test)
-
-set_property(TEST ${TEST_PREFIX}/oap_test PROPERTY SKIP_RETURN_CODE 1)
-set_property(TEST ${TEST_PREFIX}/oap_test_pqc PROPERTY SKIP_RETURN_CODE 1)
+ouroboros_register_tests(TARGET ${PARENT_DIR}_pqc_test TESTS ${${PARENT_DIR}_pqc_tests})
diff --git a/src/irmd/reg/flow.c b/src/irmd/reg/flow.c
index 02dc9c99..52b03e61 100644
--- a/src/irmd/reg/flow.c
+++ b/src/irmd/reg/flow.c
@@ -178,6 +178,7 @@ int reg_flow_update(struct reg_flow * flow,
}
flow->info.state = info->state;
+ flow->info.uid = info->uid;
*info = flow->info;
diff --git a/src/irmd/reg/pool.c b/src/irmd/reg/pool.c
new file mode 100644
index 00000000..fd983db8
--- /dev/null
+++ b/src/irmd/reg/pool.c
@@ -0,0 +1,101 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2026
+ *
+ * The IPC Resource Manager - Registry - Per-User Pools
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., http://www.fsf.org/about/contact/.
+ */
+
+#define _POSIX_C_SOURCE 200809L
+
+#define OUROBOROS_PREFIX "reg/pool"
+
+#include <ouroboros/logs.h>
+#include <ouroboros/ssm_pool.h>
+
+#include "pool.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+struct reg_pool * reg_pool_create(uid_t uid,
+ gid_t gid)
+{
+ struct reg_pool * pool;
+
+ pool = malloc(sizeof(*pool));
+ if (pool == NULL) {
+ log_err("Failed to malloc pool.");
+ goto fail_malloc;
+ }
+
+ pool->ssm = ssm_pool_create(uid, gid);
+ if (pool->ssm == NULL) {
+ log_err("Failed to create PUP for uid %d.", uid);
+ goto fail_ssm;
+ }
+
+ list_head_init(&pool->next);
+ pool->uid = uid;
+ pool->gid = gid;
+ pool->refcount = 1;
+
+ log_dbg("Created PUP for uid %d gid %d.", uid, gid);
+
+ return pool;
+
+ fail_ssm:
+ free(pool);
+ fail_malloc:
+ return NULL;
+}
+
+void reg_pool_destroy(struct reg_pool * pool)
+{
+ assert(pool != NULL);
+ assert(pool->refcount == 0);
+
+ log_dbg("Destroying PUP for uid %d.", pool->uid);
+
+ ssm_pool_destroy(pool->ssm);
+
+ assert(list_is_empty(&pool->next));
+
+ free(pool);
+}
+
+void reg_pool_ref(struct reg_pool * pool)
+{
+ assert(pool != NULL);
+ assert(pool->refcount > 0);
+
+ pool->refcount++;
+
+ log_dbg("PUP uid %d refcount++ -> %zu.", pool->uid, pool->refcount);
+}
+
+int reg_pool_unref(struct reg_pool * pool)
+{
+ assert(pool != NULL);
+ assert(pool->refcount > 0);
+
+ pool->refcount--;
+
+ log_dbg("PUP uid %d refcount-- -> %zu.", pool->uid, pool->refcount);
+
+ return pool->refcount == 0 ? 0 : 1;
+}
diff --git a/src/irmd/reg/pool.h b/src/irmd/reg/pool.h
new file mode 100644
index 00000000..576f491c
--- /dev/null
+++ b/src/irmd/reg/pool.h
@@ -0,0 +1,48 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2026
+ *
+ * The IPC Resource Manager - Registry - Per-User Pools
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., http://www.fsf.org/about/contact/.
+ */
+
+#ifndef OUROBOROS_IRMD_REG_POOL_H
+#define OUROBOROS_IRMD_REG_POOL_H
+
+#include <ouroboros/list.h>
+#include <ouroboros/ssm_pool.h>
+
+#include <sys/types.h>
+
+struct reg_pool {
+ struct list_head next;
+ uid_t uid;
+ gid_t gid;
+ size_t refcount;
+ struct ssm_pool * ssm;
+};
+
+struct reg_pool * reg_pool_create(uid_t uid,
+ gid_t gid);
+
+void reg_pool_destroy(struct reg_pool * pool);
+
+void reg_pool_ref(struct reg_pool * pool);
+
+int reg_pool_unref(struct reg_pool * pool);
+
+#endif /* OUROBOROS_IRMD_REG_POOL_H */
diff --git a/src/irmd/reg/proc.c b/src/irmd/reg/proc.c
index 541731b2..b97dcf2d 100644
--- a/src/irmd/reg/proc.c
+++ b/src/irmd/reg/proc.c
@@ -25,6 +25,7 @@
#define OUROBOROS_PREFIX "reg/proc"
#include <ouroboros/logs.h>
+#include <ouroboros/utils.h>
#include "proc.h"
@@ -75,6 +76,8 @@ struct reg_proc * reg_proc_create(const struct proc_info * info)
goto fail_malloc;
}
+ memset(proc, 0, sizeof(*proc));
+
proc->set = ssm_flow_set_create(info->pid);
if (proc->set == NULL) {
log_err("Failed to create flow set for %d.", info->pid);
@@ -181,3 +184,10 @@ bool reg_proc_has_name(const struct reg_proc * proc,
{
return __reg_proc_get_name(proc, name) != NULL;
}
+
+bool reg_proc_is_privileged(const struct reg_proc * proc)
+{
+ assert(proc != NULL);
+
+ return is_ouroboros_member_uid(proc->info.uid);
+}
diff --git a/src/irmd/reg/proc.h b/src/irmd/reg/proc.h
index a790e5c9..be4c1161 100644
--- a/src/irmd/reg/proc.h
+++ b/src/irmd/reg/proc.h
@@ -53,4 +53,6 @@ void reg_proc_del_name(struct reg_proc * proc,
bool reg_proc_has_name(const struct reg_proc * proc,
const char * name);
+bool reg_proc_is_privileged(const struct reg_proc * proc);
+
#endif /* OUROBOROS_IRMD_REG_PROC_H */
diff --git a/src/irmd/reg/reg.c b/src/irmd/reg/reg.c
index fd8285be..e89b492b 100644
--- a/src/irmd/reg/reg.c
+++ b/src/irmd/reg/reg.c
@@ -35,6 +35,7 @@ The IPC Resource Manager - Registry
#include "flow.h"
#include "ipcp.h"
#include "name.h"
+#include "pool.h"
#include "proc.h"
#include "prog.h"
@@ -57,6 +58,9 @@ struct {
struct list_head names; /* registered names known */
size_t n_names; /* number of names */
+ struct list_head pools; /* per-user pools */
+ size_t n_pools; /* number of pools */
+
struct list_head procs; /* processes */
size_t n_procs; /* number of processes */
@@ -235,6 +239,20 @@ static struct list_head * __reg_after_name(const char * name)
return p;
}
+static struct reg_pool * __reg_get_pool(uid_t uid)
+{
+ struct list_head * p;
+
+ list_for_each(p, &reg.pools) {
+ struct reg_pool * entry;
+ entry = list_entry(p, struct reg_pool, next);
+ if (entry->uid == uid)
+ return entry;
+ }
+
+ return NULL;
+}
+
static struct reg_proc * __reg_get_proc(pid_t pid)
{
struct list_head * p;
@@ -540,6 +558,7 @@ int reg_init(void)
list_head_init(&reg.flows);
list_head_init(&reg.ipcps);
list_head_init(&reg.names);
+ list_head_init(&reg.pools);
list_head_init(&reg.procs);
list_head_init(&reg.progs);
list_head_init(&reg.spawned);
@@ -589,6 +608,15 @@ void reg_clear(void)
reg.n_procs--;
}
+ list_for_each_safe(p, h, &reg.pools) {
+ struct reg_pool * entry;
+ entry = list_entry(p, struct reg_pool, next);
+ list_del(&entry->next);
+ entry->refcount = 0; /* Force destroy during cleanup */
+ reg_pool_destroy(entry);
+ reg.n_pools--;
+ }
+
list_for_each_safe(p, h, &reg.flows) {
struct reg_flow * entry;
entry = list_entry(p, struct reg_flow, next);
@@ -621,6 +649,7 @@ void reg_fini(void)
assert(list_is_empty(&reg.spawned));
assert(list_is_empty(&reg.progs));
assert(list_is_empty(&reg.procs));
+ assert(list_is_empty(&reg.pools));
assert(list_is_empty(&reg.names));
assert(list_is_empty(&reg.ipcps));
assert(list_is_empty(&reg.flows));
@@ -628,6 +657,7 @@ void reg_fini(void)
assert(reg.n_spawned == 0);
assert(reg.n_progs == 0);
assert(reg.n_procs == 0);
+ assert(reg.n_pools == 0);
assert(reg.n_names == 0);
assert(reg.n_ipcps == 0);
assert(reg.n_flows == 0);
@@ -1090,6 +1120,35 @@ int reg_list_names(name_info_msg_t *** names)
return -ENOMEM;
}
+int reg_prepare_pool(uid_t uid,
+ gid_t gid)
+{
+ struct reg_pool * pool;
+
+ if (is_ouroboros_member_uid(uid))
+ return 0;
+
+ pthread_mutex_lock(&reg.mtx);
+
+ pool = __reg_get_pool(uid);
+ if (pool == NULL) {
+ pool = reg_pool_create(uid, gid);
+ if (pool == NULL) {
+ log_err("Failed to create pool for uid %d.", uid);
+ pthread_mutex_unlock(&reg.mtx);
+ return -1;
+ }
+ list_add(&pool->next, &reg.pools);
+ reg.n_pools++;
+ }
+
+ reg_pool_ref(pool);
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return 0;
+}
+
int reg_create_proc(const struct proc_info * info)
{
struct reg_proc * proc;
@@ -1100,13 +1159,13 @@ int reg_create_proc(const struct proc_info * info)
if (__reg_get_proc(info->pid) != NULL) {
log_err("Process %d already exists.", info->pid);
- goto fail_proc;
+ goto fail;
}
proc = reg_proc_create(info);
if (proc == NULL) {
log_err("Failed to create process %d.", info->pid);
- goto fail_proc;
+ goto fail;
}
__reg_proc_update_names(proc);
@@ -1121,7 +1180,7 @@ int reg_create_proc(const struct proc_info * info)
return 0;
- fail_proc:
+ fail:
pthread_mutex_unlock(&reg.mtx);
return -1;
}
@@ -1129,6 +1188,7 @@ int reg_create_proc(const struct proc_info * info)
int reg_destroy_proc(pid_t pid)
{
struct reg_proc * proc;
+ struct reg_pool * pool = NULL;
struct pid_entry * spawn;
struct reg_ipcp * ipcp;
@@ -1136,11 +1196,18 @@ int reg_destroy_proc(pid_t pid)
proc = __reg_get_proc(pid);
if (proc != NULL) {
+ if (!is_ouroboros_member_uid(proc->info.uid))
+ pool = __reg_get_pool(proc->info.uid);
list_del(&proc->next);
reg.n_procs--;
reg_proc_destroy(proc);
__reg_del_proc_from_names(pid);
__reg_cancel_flows_for_proc(pid);
+ if (pool != NULL && reg_pool_unref(pool) == 0) {
+ list_del(&pool->next);
+ reg.n_pools--;
+ reg_pool_destroy(pool);
+ }
}
spawn = __reg_get_spawned(pid);
@@ -1175,6 +1242,38 @@ bool reg_has_proc(pid_t pid)
return ret;
}
+bool reg_is_proc_privileged(pid_t pid)
+{
+ struct reg_proc * proc;
+ bool ret = false;
+
+ pthread_mutex_lock(&reg.mtx);
+
+ proc = __reg_get_proc(pid);
+ if (proc != NULL)
+ ret = reg_proc_is_privileged(proc);
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return ret;
+}
+
+uid_t reg_get_proc_uid(pid_t pid)
+{
+ struct reg_proc * proc;
+ uid_t ret = 0;
+
+ pthread_mutex_lock(&reg.mtx);
+
+ proc = __reg_get_proc(pid);
+ if (proc != NULL && !is_ouroboros_member_uid(proc->info.uid))
+ ret = proc->info.uid;
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return ret;
+}
+
void reg_kill_all_proc(int signal)
{
pthread_mutex_lock(&reg.mtx);
diff --git a/src/irmd/reg/reg.h b/src/irmd/reg/reg.h
index 7728c80f..77264fde 100644
--- a/src/irmd/reg/reg.h
+++ b/src/irmd/reg/reg.h
@@ -31,6 +31,8 @@
#include <ouroboros/time.h>
#include <ouroboros/utils.h>
+#include "pool.h"
+
int reg_init(void);
void reg_clear(void);
@@ -50,6 +52,13 @@ int reg_destroy_proc(pid_t pid);
bool reg_has_proc(pid_t pid);
+bool reg_is_proc_privileged(pid_t pid);
+
+int reg_prepare_pool(uid_t uid,
+ gid_t gid);
+
+uid_t reg_get_proc_uid(pid_t pid);
+
void reg_kill_all_proc(int signal);
pid_t reg_get_dead_proc(void);
diff --git a/src/irmd/reg/tests/CMakeLists.txt b/src/irmd/reg/tests/CMakeLists.txt
index 759d29b4..e8521545 100644
--- a/src/irmd/reg/tests/CMakeLists.txt
+++ b/src/irmd/reg/tests/CMakeLists.txt
@@ -1,17 +1,9 @@
-get_filename_component(tmp ".." ABSOLUTE)
-get_filename_component(src_folder "${tmp}" NAME)
+get_filename_component(PARENT_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
+get_filename_component(PARENT_DIR ${PARENT_PATH} NAME)
compute_test_prefix()
-# Set include directories for tests
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories(${CMAKE_BINARY_DIR}/include)
-include_directories(${CMAKE_SOURCE_DIR}/src/irmd)
-include_directories(${CMAKE_BINARY_DIR}/src/irmd)
-
-create_test_sourcelist(${src_folder}_tests test_suite.c
+create_test_sourcelist(${PARENT_DIR}_tests test_suite.c
# Add new tests here
flow_test.c
ipcp_test.c
@@ -21,25 +13,21 @@ create_test_sourcelist(${src_folder}_tests test_suite.c
reg_test.c
)
-add_executable(${src_folder}_test ${${src_folder}_tests})
-
-disable_test_logging_for_target(${src_folder}_test)
-target_link_libraries(${src_folder}_test ouroboros-common)
+add_executable(${PARENT_DIR}_test ${${PARENT_DIR}_tests})
-if (CMAKE_BUILD_TYPE MATCHES "Debug*")
- add_compile_flags(${src_folder}_test -DCONFIG_OUROBOROS_DEBUG)
-endif ()
+target_include_directories(${PARENT_DIR}_test PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_BINARY_DIR}/include
+ ${CMAKE_SOURCE_DIR}/src/irmd
+ ${CMAKE_BINARY_DIR}/src/irmd
+)
-add_dependencies(build_tests ${src_folder}_test)
+disable_test_logging_for_target(${PARENT_DIR}_test)
+target_link_libraries(${PARENT_DIR}_test PRIVATE ouroboros-common)
+ouroboros_target_debug_definitions(${PARENT_DIR}_test)
-set(tests_to_run ${${src_folder}_tests})
-if(CMAKE_VERSION VERSION_LESS "3.29.0")
- remove(tests_to_run test_suite.c)
-else ()
- list(POP_FRONT tests_to_run)
-endif()
+add_dependencies(build_tests ${PARENT_DIR}_test)
-foreach(test ${tests_to_run})
- get_filename_component(test_name ${test} NAME_WE)
- add_test(${TEST_PREFIX}/${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${src_folder}_test ${test_name})
-endforeach(test)
+ouroboros_register_tests(TARGET ${PARENT_DIR}_test TESTS ${${PARENT_DIR}_tests})
diff --git a/src/irmd/reg/tests/proc_test.c b/src/irmd/reg/tests/proc_test.c
index d53f18ec..c4e689f0 100644
--- a/src/irmd/reg/tests/proc_test.c
+++ b/src/irmd/reg/tests/proc_test.c
@@ -27,13 +27,17 @@
#define TEST_PID 65534
#define TEST_PROG "usr/bin/testprog"
+#define TEST_PROC { \
+ .pid = TEST_PID, \
+ .prog = TEST_PROG, \
+ .uid = getuid(), \
+ .gid = getgid() \
+}
+
static int test_reg_proc_create_destroy(void)
{
struct reg_proc * proc;
- struct proc_info info = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info info = TEST_PROC;
TEST_START();
@@ -56,10 +60,7 @@ static int test_reg_proc_create_destroy(void)
static int test_reg_proc_add_name(void)
{
struct reg_proc * proc;
- struct proc_info info = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info info = TEST_PROC;
char * name = "testname";
diff --git a/src/irmd/reg/tests/reg_test.c b/src/irmd/reg/tests/reg_test.c
index 07d0a198..f7a4de8e 100644
--- a/src/irmd/reg/tests/reg_test.c
+++ b/src/irmd/reg/tests/reg_test.c
@@ -21,6 +21,8 @@
*/
+#include "../pool.c"
+#undef OUROBOROS_PREFIX
#include "../reg.c"
#include <test/test.h>
@@ -35,6 +37,12 @@
#define TEST_DATA "testpbufdata"
#define TEST_DATA2 "testpbufdata2"
#define TEST_LAYER "testlayer"
+#define TEST_PROC_INFO { \
+ .pid = TEST_PID, \
+ .prog = TEST_PROG, \
+ .uid = 0, \
+ .gid = 0 \
+}
#define REG_TEST_FAIL() \
do { TEST_FAIL(); reg_clear(); return TEST_RC_FAIL;} while(0)
@@ -852,10 +860,7 @@ static int test_reg_name(void)
static int test_reg_create_proc(void)
{
- struct proc_info info = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info info = TEST_PROC_INFO;
TEST_START();
@@ -1011,10 +1016,7 @@ static int test_reg_prog(void)
static int test_bind_proc(void)
{
- struct proc_info pinfo = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info pinfo = TEST_PROC_INFO;
struct name_info ninfo = {
.name = TEST_NAME,
@@ -1167,10 +1169,7 @@ static int test_inherit_prog(void)
.name = TEST_PROG
};
- struct proc_info procinfo = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info procinfo = TEST_PROC_INFO;
char * exec[] = { TEST_PROG, NULL};
@@ -1308,10 +1307,7 @@ static void * test_call_flow_accept(void * o)
struct timespec timeo = TIMESPEC_INIT_MS(10);
buffer_t pbuf = BUF_INIT;
- struct proc_info pinfo = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info pinfo = TEST_PROC_INFO;
struct flow_info info = {
.n_pid = pinfo.pid,
@@ -1663,10 +1659,7 @@ static int test_wait_proc_success(void)
struct timespec abstime;
struct timespec timeo = TIMESPEC_INIT_S(10);
pthread_t thr;
- struct proc_info info = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info info = TEST_PROC_INFO;
TEST_START();
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
new file mode 100644
index 00000000..c4306b00
--- /dev/null
+++ b/src/lib/CMakeLists.txt
@@ -0,0 +1,160 @@
+# Ouroboros libraries build configuration
+# Configuration options are in cmake/config/lib.cmake
+
+protobuf_generate_c(MODEL_PROTO_SRCS MODEL_PROTO_HDRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/pb/model.proto")
+protobuf_generate_c(IPCP_CONFIG_PROTO_SRCS IPCP_CONFIG_PROTO_HDRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/pb/ipcp_config.proto")
+protobuf_generate_c(ENROLL_PROTO_SRCS ENROLL_PROTO_HDRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/pb/enroll.proto")
+protobuf_generate_c(CEP_PROTO_SRCS CEP_PROTO_HDRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/pb/cep.proto")
+protobuf_generate_c(IRM_PROTO_SRCS IRM_PROTO_HDRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/pb/irm.proto")
+protobuf_generate_c(IPCP_PROTO_SRCS IPCP_PROTO_HDRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/pb/ipcp.proto")
+
+set(SOURCE_FILES_COMMON
+ bitmap.c
+ btree.c
+ crc32.c
+ crypt.c
+ hash.c
+ list.c
+ lockfile.c
+ logs.c
+ md5.c
+ notifier.c
+ protobuf.c
+ qoscube.c
+ random.c
+ rib.c
+ serdes-irm.c
+ serdes-oep.c
+ sha3.c
+ ssm/flow_set.c
+ ssm/rbuff.c
+ ssm/pool.c
+ sockets.c
+ tpm.c
+ utils.c
+)
+
+if(HAVE_OPENSSL)
+ list(APPEND SOURCE_FILES_COMMON crypt/openssl.c)
+endif()
+
+add_library(ouroboros-common SHARED
+ ${SOURCE_FILES_COMMON}
+ ${IRM_PROTO_SRCS}
+ ${IPCP_PROTO_SRCS}
+ ${IPCP_CONFIG_PROTO_SRCS}
+ ${MODEL_PROTO_SRCS}
+ ${ENROLL_PROTO_SRCS})
+
+set_target_properties(ouroboros-common PROPERTIES
+ VERSION ${PACKAGE_VERSION}
+ SOVERSION ${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR})
+
+ouroboros_target_debug_definitions(ouroboros-common)
+
+target_include_directories(ouroboros-common
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
+ $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
+ $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ PRIVATE
+ ${SYS_RND_HDR}
+ ${APPLE_INCLUDE_DIRS})
+
+target_link_libraries(ouroboros-common
+ PRIVATE
+ ${LIBRT_LIBRARIES}
+ Threads::Threads
+ PUBLIC
+ ProtobufC::ProtobufC)
+
+if(HAVE_OPENSSL)
+ target_link_libraries(ouroboros-common PUBLIC OpenSSL::Crypto)
+endif()
+
+if(HAVE_LIBGCRYPT)
+ target_link_libraries(ouroboros-common PUBLIC Gcrypt::Gcrypt)
+endif()
+
+if(HAVE_FUSE)
+ target_link_libraries(ouroboros-common PRIVATE Fuse::Fuse)
+endif()
+
+install(TARGETS ouroboros-common
+ EXPORT OuroborosTargets
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
+set(SOURCE_FILES_DEV
+ cep.c
+ dev.c
+)
+
+add_library(ouroboros-dev SHARED
+ ${SOURCE_FILES_DEV}
+ ${CEP_PROTO_SRCS})
+
+set_target_properties(ouroboros-dev PROPERTIES
+ VERSION ${PACKAGE_VERSION}
+ SOVERSION ${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR})
+
+ouroboros_target_debug_definitions(ouroboros-dev)
+
+target_include_directories(ouroboros-dev
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${SYS_RND_HDR})
+
+target_link_libraries(ouroboros-dev PUBLIC ouroboros-common)
+
+install(TARGETS ouroboros-dev
+ EXPORT OuroborosTargets
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
+add_library(ouroboros-irm SHARED irm.c)
+
+set_target_properties(ouroboros-irm PROPERTIES
+ VERSION ${PACKAGE_VERSION}
+ SOVERSION ${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR})
+
+ouroboros_target_debug_definitions(ouroboros-irm)
+
+target_include_directories(ouroboros-irm
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${SYS_RND_HDR})
+
+target_link_libraries(ouroboros-irm PUBLIC ouroboros-common)
+
+install(TARGETS ouroboros-irm
+ EXPORT OuroborosTargets
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/config.h" @ONLY)
+
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ssm/ssm.h.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/ssm.h" @ONLY)
+
+if(BUILD_TESTS)
+ add_subdirectory(tests)
+ add_subdirectory(ssm/tests)
+endif()
diff --git a/src/lib/crypt.c b/src/lib/crypt.c
index 38dd9f29..8c29cbb3 100644
--- a/src/lib/crypt.c
+++ b/src/lib/crypt.c
@@ -20,6 +20,10 @@
* Foundation, Inc., http://www.fsf.org/about/contact/.
*/
+#if defined(__linux__) || defined(__CYGWIN__)
+#define _DEFAULT_SOURCE
+#endif
+
#include <config.h>
#include <ouroboros/errno.h>
diff --git a/src/lib/dev.c b/src/lib/dev.c
index fb06c496..454dd027 100644
--- a/src/lib/dev.c
+++ b/src/lib/dev.c
@@ -127,7 +127,7 @@ struct fqueue {
};
struct {
- struct ssm_pool * gspp;
+ struct ssm_pool * pool;
struct ssm_flow_set * fqset;
struct bmp * fds;
@@ -146,14 +146,14 @@ struct {
fset_t * frct_set;
pthread_rwlock_t lock;
-} ai;
+} proc;
static void flow_destroy(struct fmap * p)
{
- pthread_mutex_lock(&ai.mtx);
+ pthread_mutex_lock(&proc.mtx);
if (p->state == FLOW_DESTROY) {
- pthread_mutex_unlock(&ai.mtx);
+ pthread_mutex_unlock(&proc.mtx);
return;
}
@@ -162,12 +162,12 @@ static void flow_destroy(struct fmap * p)
else
p->state = FLOW_NULL;
- pthread_cond_signal(&ai.cond);
+ pthread_cond_signal(&proc.cond);
- pthread_cleanup_push(__cleanup_mutex_unlock, &ai.mtx);
+ pthread_cleanup_push(__cleanup_mutex_unlock, &proc.mtx);
while (p->state != FLOW_NULL)
- pthread_cond_wait(&ai.cond, &ai.mtx);
+ pthread_cond_wait(&proc.cond, &proc.mtx);
p->fd = -1;
p->state = FLOW_INIT;
@@ -178,17 +178,17 @@ static void flow_destroy(struct fmap * p)
static void flow_set_state(struct fmap * p,
enum flow_state state)
{
- pthread_mutex_lock(&ai.mtx);
+ pthread_mutex_lock(&proc.mtx);
if (p->state == FLOW_DESTROY) {
- pthread_mutex_unlock(&ai.mtx);
+ pthread_mutex_unlock(&proc.mtx);
return;
}
p->state = state;
- pthread_cond_broadcast(&ai.cond);
+ pthread_cond_broadcast(&proc.cond);
- pthread_mutex_unlock(&ai.mtx);
+ pthread_mutex_unlock(&proc.mtx);
}
static enum flow_state flow_wait_assign(int flow_id)
@@ -196,26 +196,26 @@ static enum flow_state flow_wait_assign(int flow_id)
enum flow_state state;
struct fmap * p;
- p = &ai.id_to_fd[flow_id];
+ p = &proc.id_to_fd[flow_id];
- pthread_mutex_lock(&ai.mtx);
+ pthread_mutex_lock(&proc.mtx);
if (p->state == FLOW_ALLOCATED) {
- pthread_mutex_unlock(&ai.mtx);
+ pthread_mutex_unlock(&proc.mtx);
return FLOW_ALLOCATED;
}
if (p->state == FLOW_INIT)
p->state = FLOW_ALLOC_PENDING;
- pthread_cleanup_push(__cleanup_mutex_unlock, &ai.mtx);
+ pthread_cleanup_push(__cleanup_mutex_unlock, &proc.mtx);
while (p->state == FLOW_ALLOC_PENDING)
- pthread_cond_wait(&ai.cond, &ai.mtx);
+ pthread_cond_wait(&proc.cond, &proc.mtx);
if (p->state == FLOW_DESTROY) {
p->state = FLOW_NULL;
- pthread_cond_broadcast(&ai.cond);
+ pthread_cond_broadcast(&proc.cond);
}
state = p->state;
@@ -227,13 +227,13 @@ static enum flow_state flow_wait_assign(int flow_id)
return state;
}
-static int proc_announce(const char * prog)
+static int proc_announce(const struct proc_info * proc)
{
uint8_t buf[SOCK_BUF_SIZE];
buffer_t msg = {SOCK_BUF_SIZE, buf};
int err;
- if (proc_announce__irm_req_ser(&msg, prog) < 0)
+ if (proc_announce__irm_req_ser(&msg, proc) < 0)
return -ENOMEM;
err = send_recv_msg(&msg);
@@ -342,23 +342,23 @@ static void flow_send_keepalive(struct flow * flow,
ssize_t idx;
uint8_t * ptr;
- idx = ssm_pool_alloc(ai.gspp, 0, &ptr, &spb);
+ idx = ssm_pool_alloc(proc.pool, 0, &ptr, &spb);
if (idx < 0)
return;
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
flow->snd_act = now;
if (ssm_rbuff_write(flow->tx_rb, idx))
- ssm_pool_remove(ai.gspp, idx);
+ ssm_pool_remove(proc.pool, idx);
else
ssm_flow_set_notify(flow->set, flow->info.id, FLOW_PKT);
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
}
-/* Needs rdlock on ai. */
+/* Needs rdlock on proc. */
static void _flow_keepalive(struct flow * flow)
{
struct timespec now;
@@ -382,16 +382,16 @@ static void _flow_keepalive(struct flow * flow)
if (ts_diff_ns(&now, &r_act) > (int64_t) timeo * MILLION) {
ssm_rbuff_set_acl(flow->rx_rb, ACL_FLOWPEER);
- ssm_flow_set_notify(ai.fqset, flow_id, FLOW_PEER);
+ ssm_flow_set_notify(proc.fqset, flow_id, FLOW_PEER);
return;
}
if (ts_diff_ns(&now, &s_act) > (int64_t) timeo * (MILLION >> 2)) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
flow_send_keepalive(flow, now);
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
}
}
@@ -400,15 +400,15 @@ static void handle_keepalives(void)
struct list_head * p;
struct list_head * h;
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
- list_for_each_safe(p, h, &ai.flow_list) {
+ list_for_each_safe(p, h, &proc.flow_list) {
struct flow * flow;
flow = list_entry(p, struct flow, next);
_flow_keepalive(flow);
}
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
}
static void __cleanup_fqueue_destroy(void * fq)
@@ -429,7 +429,7 @@ void * flow_rx(void * o)
pthread_cleanup_push(__cleanup_fqueue_destroy, fq);
/* fevent will filter all FRCT packets for us */
- while ((ret = fevent(ai.frct_set, fq, &tic)) != 0) {
+ while ((ret = fevent(proc.frct_set, fq, &tic)) != 0) {
if (ret == -ETIMEDOUT) {
handle_keepalives();
continue;
@@ -446,63 +446,63 @@ void * flow_rx(void * o)
static void flow_clear(int fd)
{
- memset(&ai.flows[fd], 0, sizeof(ai.flows[fd]));
+ memset(&proc.flows[fd], 0, sizeof(proc.flows[fd]));
- ai.flows[fd].info.id = -1;
+ proc.flows[fd].info.id = -1;
}
static void __flow_fini(int fd)
{
assert(fd >= 0 && fd < SYS_MAX_FLOWS);
- if (ai.flows[fd].frcti != NULL) {
- ai.n_frcti--;
- if (ai.n_frcti == 0) {
- pthread_cancel(ai.tx);
- pthread_join(ai.tx, NULL);
+ if (proc.flows[fd].frcti != NULL) {
+ proc.n_frcti--;
+ if (proc.n_frcti == 0) {
+ pthread_cancel(proc.tx);
+ pthread_join(proc.tx, NULL);
}
- ssm_flow_set_del(ai.fqset, 0, ai.flows[fd].info.id);
+ ssm_flow_set_del(proc.fqset, 0, proc.flows[fd].info.id);
- frcti_destroy(ai.flows[fd].frcti);
+ frcti_destroy(proc.flows[fd].frcti);
}
- if (ai.flows[fd].info.id != -1) {
- flow_destroy(&ai.id_to_fd[ai.flows[fd].info.id]);
- bmp_release(ai.fds, fd);
+ if (proc.flows[fd].info.id != -1) {
+ flow_destroy(&proc.id_to_fd[proc.flows[fd].info.id]);
+ bmp_release(proc.fds, fd);
}
- if (ai.flows[fd].rx_rb != NULL) {
- ssm_rbuff_set_acl(ai.flows[fd].rx_rb, ACL_FLOWDOWN);
- ssm_rbuff_close(ai.flows[fd].rx_rb);
+ if (proc.flows[fd].rx_rb != NULL) {
+ ssm_rbuff_set_acl(proc.flows[fd].rx_rb, ACL_FLOWDOWN);
+ ssm_rbuff_close(proc.flows[fd].rx_rb);
}
- if (ai.flows[fd].tx_rb != NULL) {
- ssm_rbuff_set_acl(ai.flows[fd].tx_rb, ACL_FLOWDOWN);
- ssm_rbuff_close(ai.flows[fd].tx_rb);
+ if (proc.flows[fd].tx_rb != NULL) {
+ ssm_rbuff_set_acl(proc.flows[fd].tx_rb, ACL_FLOWDOWN);
+ ssm_rbuff_close(proc.flows[fd].tx_rb);
}
- if (ai.flows[fd].set != NULL) {
- ssm_flow_set_notify(ai.flows[fd].set,
- ai.flows[fd].info.id,
+ if (proc.flows[fd].set != NULL) {
+ ssm_flow_set_notify(proc.flows[fd].set,
+ proc.flows[fd].info.id,
FLOW_DEALLOC);
- ssm_flow_set_close(ai.flows[fd].set);
+ ssm_flow_set_close(proc.flows[fd].set);
}
- crypt_destroy_ctx(ai.flows[fd].crypt);
+ crypt_destroy_ctx(proc.flows[fd].crypt);
- list_del(&ai.flows[fd].next);
+ list_del(&proc.flows[fd].next);
flow_clear(fd);
}
static void flow_fini(int fd)
{
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
__flow_fini(fd);
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
}
#define IS_ENCRYPTED(crypt) ((crypt)->nid != NID_undef)
@@ -517,15 +517,15 @@ static int flow_init(struct flow_info * info,
clock_gettime(PTHREAD_COND_CLOCK, &now);
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
- fd = bmp_allocate(ai.fds);
- if (!bmp_is_id_valid(ai.fds, fd)) {
+ fd = bmp_allocate(proc.fds);
+ if (!bmp_is_id_valid(proc.fds, fd)) {
err = -EBADF;
goto fail_fds;
}
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
flow->info = *info;
@@ -566,27 +566,27 @@ static int flow_init(struct flow_info * info,
if (flow->frcti == NULL)
goto fail_frcti;
- if (ssm_flow_set_add(ai.fqset, 0, info->id))
+ if (ssm_flow_set_add(proc.fqset, 0, info->id))
goto fail_flow_set_add;
- ++ai.n_frcti;
- if (ai.n_frcti == 1 &&
- pthread_create(&ai.tx, NULL, flow_tx, NULL) < 0)
+ ++proc.n_frcti;
+ if (proc.n_frcti == 1 &&
+ pthread_create(&proc.tx, NULL, flow_tx, NULL) < 0)
goto fail_tx_thread;
}
- list_add_tail(&flow->next, &ai.flow_list);
+ list_add_tail(&flow->next, &proc.flow_list);
- ai.id_to_fd[info->id].fd = fd;
+ proc.id_to_fd[info->id].fd = fd;
- flow_set_state(&ai.id_to_fd[info->id], FLOW_ALLOCATED);
+ flow_set_state(&proc.id_to_fd[info->id], FLOW_ALLOCATED);
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return fd;
fail_tx_thread:
- ssm_flow_set_del(ai.fqset, 0, info->id);
+ ssm_flow_set_del(proc.fqset, 0, info->id);
fail_flow_set_add:
frcti_destroy(flow->frcti);
fail_frcti:
@@ -598,9 +598,9 @@ static int flow_init(struct flow_info * info,
fail_tx_rb:
ssm_rbuff_close(flow->rx_rb);
fail_rx_rb:
- bmp_release(ai.fds, fd);
+ bmp_release(proc.fds, fd);
fail_fds:
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return err;
}
@@ -618,6 +618,7 @@ static void init(int argc,
char ** argv,
char ** envp)
{
+ struct proc_info info;
char * prog = argv[0];
int i;
#ifdef PROC_FLOW_STATS
@@ -635,7 +636,11 @@ static void init(int argc,
goto fail_prog;
}
- if (proc_announce(prog)) {
+ memset(&info, 0, sizeof(info));
+ info.pid = getpid();
+ strncpy(info.prog, prog, PROG_NAME_SIZE);
+
+ if (proc_announce(&info)) {
fprintf(stderr, "FATAL: Could not announce to IRMd.\n");
goto fail_prog;
}
@@ -650,26 +655,30 @@ static void init(int argc,
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
}
#endif
- ai.fds = bmp_create(PROG_MAX_FLOWS - PROG_RES_FDS, PROG_RES_FDS);
- if (ai.fds == NULL) {
+ proc.fds = bmp_create(PROG_MAX_FLOWS - PROG_RES_FDS, PROG_RES_FDS);
+ if (proc.fds == NULL) {
fprintf(stderr, "FATAL: Could not create fd bitmap.\n");
goto fail_fds;
}
- ai.fqueues = bmp_create(PROG_MAX_FQUEUES, 0);
- if (ai.fqueues == NULL) {
+ proc.fqueues = bmp_create(PROG_MAX_FQUEUES, 0);
+ if (proc.fqueues == NULL) {
fprintf(stderr, "FATAL: Could not create fqueue bitmap.\n");
goto fail_fqueues;
}
- ai.gspp = ssm_pool_open();
- if (ai.gspp == NULL) {
+ if (is_ouroboros_member_uid(getuid()))
+ proc.pool = ssm_pool_open(0);
+ else
+ proc.pool = ssm_pool_open(getuid());
+
+ if (proc.pool == NULL) {
fprintf(stderr, "FATAL: Could not open packet buffer.\n");
goto fail_rdrb;
}
- ai.flows = malloc(sizeof(*ai.flows) * PROG_MAX_FLOWS);
- if (ai.flows == NULL) {
+ proc.flows = malloc(sizeof(*proc.flows) * PROG_MAX_FLOWS);
+ if (proc.flows == NULL) {
fprintf(stderr, "FATAL: Could not malloc flows.\n");
goto fail_flows;
}
@@ -677,38 +686,38 @@ static void init(int argc,
for (i = 0; i < PROG_MAX_FLOWS; ++i)
flow_clear(i);
- ai.id_to_fd = malloc(sizeof(*ai.id_to_fd) * SYS_MAX_FLOWS);
- if (ai.id_to_fd == NULL) {
+ proc.id_to_fd = malloc(sizeof(*proc.id_to_fd) * SYS_MAX_FLOWS);
+ if (proc.id_to_fd == NULL) {
fprintf(stderr, "FATAL: Could not malloc id_to_fd.\n");
goto fail_id_to_fd;
}
for (i = 0; i < SYS_MAX_FLOWS; ++i)
- ai.id_to_fd[i].state = FLOW_INIT;
+ proc.id_to_fd[i].state = FLOW_INIT;
- if (pthread_mutex_init(&ai.mtx, NULL)) {
+ if (pthread_mutex_init(&proc.mtx, NULL)) {
fprintf(stderr, "FATAL: Could not init mutex.\n");
goto fail_mtx;
}
- if (pthread_cond_init(&ai.cond, NULL) < 0) {
+ if (pthread_cond_init(&proc.cond, NULL) < 0) {
fprintf(stderr, "FATAL: Could not init condvar.\n");
goto fail_cond;
}
- if (pthread_rwlock_init(&ai.lock, NULL) < 0) {
+ if (pthread_rwlock_init(&proc.lock, NULL) < 0) {
fprintf(stderr, "FATAL: Could not initialize flow lock.\n");
goto fail_flow_lock;
}
- ai.fqset = ssm_flow_set_open(getpid());
- if (ai.fqset == NULL) {
+ proc.fqset = ssm_flow_set_open(getpid());
+ if (proc.fqset == NULL) {
fprintf(stderr, "FATAL: Could not open flow set.\n");
goto fail_fqset;
}
- ai.frct_set = fset_create();
- if (ai.frct_set == NULL || ai.frct_set->idx != 0) {
+ proc.frct_set = fset_create();
+ if (proc.frct_set == NULL || proc.frct_set->idx != 0) {
fprintf(stderr, "FATAL: Could not create FRCT set.\n");
goto fail_frct_set;
}
@@ -732,12 +741,12 @@ static void init(int argc,
}
}
#endif
- if (pthread_create(&ai.rx, NULL, flow_rx, NULL) < 0) {
+ if (pthread_create(&proc.rx, NULL, flow_rx, NULL) < 0) {
fprintf(stderr, "FATAL: Could not start monitor thread.\n");
goto fail_monitor;
}
- list_head_init(&ai.flow_list);
+ list_head_init(&proc.flow_list);
return;
@@ -748,27 +757,27 @@ static void init(int argc,
#endif
timerwheel_fini();
fail_timerwheel:
- fset_destroy(ai.frct_set);
+ fset_destroy(proc.frct_set);
fail_frct_set:
- ssm_flow_set_close(ai.fqset);
+ ssm_flow_set_close(proc.fqset);
fail_fqset:
- pthread_rwlock_destroy(&ai.lock);
+ pthread_rwlock_destroy(&proc.lock);
fail_flow_lock:
- pthread_cond_destroy(&ai.cond);
+ pthread_cond_destroy(&proc.cond);
fail_cond:
- pthread_mutex_destroy(&ai.mtx);
+ pthread_mutex_destroy(&proc.mtx);
fail_mtx:
- free(ai.id_to_fd);
+ free(proc.id_to_fd);
fail_id_to_fd:
- free(ai.flows);
+ free(proc.flows);
fail_flows:
- ssm_pool_close(ai.gspp);
+ ssm_pool_close(proc.pool);
fail_rdrb:
- bmp_destroy(ai.fqueues);
+ bmp_destroy(proc.fqueues);
fail_fqueues:
- bmp_destroy(ai.fds);
+ bmp_destroy(proc.fds);
fail_fds:
- memset(&ai, 0, sizeof(ai));
+ memset(&proc, 0, sizeof(proc));
fail_prog:
exit(EXIT_FAILURE);
}
@@ -777,51 +786,52 @@ static void fini(void)
{
int i;
- if (ai.fds == NULL)
+ if (proc.fds == NULL)
return;
- pthread_cancel(ai.rx);
- pthread_join(ai.rx, NULL);
+ pthread_cancel(proc.rx);
+ pthread_join(proc.rx, NULL);
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
for (i = 0; i < PROG_MAX_FLOWS; ++i) {
- if (ai.flows[i].info.id != -1) {
+ struct flow * flow = &proc.flows[i];
+ if (flow->info.id != -1) {
ssize_t idx;
- ssm_rbuff_set_acl(ai.flows[i].rx_rb, ACL_FLOWDOWN);
- while ((idx = ssm_rbuff_read(ai.flows[i].rx_rb)) >= 0)
- ssm_pool_remove(ai.gspp, idx);
+ ssm_rbuff_set_acl(flow->rx_rb, ACL_FLOWDOWN);
+ while ((idx = ssm_rbuff_read(flow->rx_rb)) >= 0)
+ ssm_pool_remove(proc.pool, idx);
__flow_fini(i);
}
}
- pthread_cond_destroy(&ai.cond);
- pthread_mutex_destroy(&ai.mtx);
+ pthread_cond_destroy(&proc.cond);
+ pthread_mutex_destroy(&proc.mtx);
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
#ifdef PROC_FLOW_STATS
rib_fini();
#endif
timerwheel_fini();
- fset_destroy(ai.frct_set);
+ fset_destroy(proc.frct_set);
- ssm_flow_set_close(ai.fqset);
+ ssm_flow_set_close(proc.fqset);
- pthread_rwlock_destroy(&ai.lock);
+ pthread_rwlock_destroy(&proc.lock);
- free(ai.flows);
- free(ai.id_to_fd);
+ free(proc.flows);
+ free(proc.id_to_fd);
- ssm_pool_close(ai.gspp);
+ ssm_pool_close(proc.pool);
- bmp_destroy(ai.fds);
- bmp_destroy(ai.fqueues);
+ bmp_destroy(proc.fds);
+ bmp_destroy(proc.fqueues);
proc_exit();
- memset(&ai, 0, sizeof(ai));
+ memset(&proc, 0, sizeof(proc));
}
#if defined(__MACH__) && defined(__APPLE__)
@@ -978,12 +988,12 @@ int flow_dealloc(int fd)
memset(&info, 0, sizeof(flow));
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
if (flow->info.id < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return -ENOTALLOC;
}
@@ -992,21 +1002,21 @@ int flow_dealloc(int fd)
flow->rcv_timesout = true;
flow->rcv_timeo = tic;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
flow_read(fd, buf, SOCK_BUF_SIZE);
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
timeo.tv_sec = frcti_dealloc(flow->frcti);
while (timeo.tv_sec < 0) { /* keep the flow active for rtx */
ssize_t ret;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
ret = flow_read(fd, pkt, PKT_BUF_LEN);
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
timeo.tv_sec = frcti_dealloc(flow->frcti);
@@ -1014,7 +1024,7 @@ int flow_dealloc(int fd)
timeo.tv_sec = -timeo.tv_sec;
}
- pthread_cleanup_push(__cleanup_rwlock_unlock, &ai.lock);
+ pthread_cleanup_push(__cleanup_rwlock_unlock, &proc.lock);
ssm_rbuff_fini(flow->tx_rb);
@@ -1048,21 +1058,21 @@ int ipcp_flow_dealloc(int fd)
if (fd < 0 || fd >= SYS_MAX_FLOWS )
return -EINVAL;
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
memset(&info, 0, sizeof(flow));
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
if (flow->info.id < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return -ENOTALLOC;
}
info.id = flow->info.id;
info.n_1_pid = flow->info.n_1_pid;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
if (ipcp_flow_dealloc__irm_req_ser(&msg, &info) < 0)
return -ENOMEM;
@@ -1096,14 +1106,14 @@ int fccntl(int fd,
if (fd < 0 || fd >= SYS_MAX_FLOWS)
return -EBADF;
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
va_start(l, cmd);
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
if (flow->info.id < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
va_end(l);
return -ENOTALLOC;
}
@@ -1209,24 +1219,24 @@ int fccntl(int fd,
*cflags = frcti_getflags(flow->frcti);
break;
default:
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
va_end(l);
return -ENOTSUP;
};
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
va_end(l);
return 0;
einval:
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
va_end(l);
return -EINVAL;
eperm:
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
va_end(l);
return -EPERM;
}
@@ -1268,15 +1278,15 @@ static int flow_tx_spb(struct flow * flow,
clock_gettime(PTHREAD_COND_CLOCK, &now);
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
flow->snd_act = now;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
idx = ssm_pk_buff_get_idx(spb);
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
if (ssm_pk_buff_len(spb) > 0) {
if (frcti_snd(flow->frcti, spb) < 0)
@@ -1289,7 +1299,7 @@ static int flow_tx_spb(struct flow * flow,
goto enomem;
}
- pthread_cleanup_push(__cleanup_rwlock_unlock, &ai.lock);
+ pthread_cleanup_push(__cleanup_rwlock_unlock, &proc.lock);
if (!block)
ret = ssm_rbuff_write(flow->tx_rb, idx);
@@ -1297,7 +1307,7 @@ static int flow_tx_spb(struct flow * flow,
ret = ssm_rbuff_write_b(flow->tx_rb, idx, abstime);
if (ret < 0)
- ssm_pool_remove(ai.gspp, idx);
+ ssm_pool_remove(proc.pool, idx);
else
ssm_flow_set_notify(flow->set, flow->info.id, FLOW_PKT);
@@ -1306,8 +1316,8 @@ static int flow_tx_spb(struct flow * flow,
return 0;
enomem:
- pthread_rwlock_unlock(&ai.lock);
- ssm_pool_remove(ai.gspp, idx);
+ pthread_rwlock_unlock(&proc.lock);
+ ssm_pool_remove(proc.pool, idx);
return -ENOMEM;
}
@@ -1330,14 +1340,14 @@ ssize_t flow_write(int fd,
if (fd < 0 || fd >= PROG_MAX_FLOWS)
return -EBADF;
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
clock_gettime(PTHREAD_COND_CLOCK, &abs);
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
if (flow->info.id < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return -ENOTALLOC;
}
@@ -1348,7 +1358,7 @@ ssize_t flow_write(int fd,
flags = flow->oflags;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
if ((flags & FLOWFACCMODE) == FLOWFRDONLY)
return -EPERM;
@@ -1356,12 +1366,12 @@ ssize_t flow_write(int fd,
if (flags & FLOWFWNOBLOCK) {
if (!frcti_is_window_open(flow->frcti))
return -EAGAIN;
- idx = ssm_pool_alloc(ai.gspp, count, &ptr, &spb);
+ idx = ssm_pool_alloc(proc.pool, count, &ptr, &spb);
} else {
ret = frcti_window_wait(flow->frcti, abstime);
if (ret < 0)
return ret;
- idx = ssm_pool_alloc_b(ai.gspp, count, &ptr, &spb, abstime);
+ idx = ssm_pool_alloc_b(proc.pool, count, &ptr, &spb, abstime);
}
if (idx < 0)
@@ -1405,16 +1415,16 @@ static ssize_t flow_rx_spb(struct flow * flow,
clock_gettime(PTHREAD_COND_CLOCK, &now);
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
flow->rcv_act = now;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
- *spb = ssm_pool_get(ai.gspp, idx);
+ *spb = ssm_pool_get(proc.pool, idx);
if (invalid_pkt(flow, *spb)) {
- ssm_pool_remove(ai.gspp, idx);
+ ssm_pool_remove(proc.pool, idx);
return -EAGAIN;
}
@@ -1439,19 +1449,19 @@ ssize_t flow_read(int fd,
if (fd < 0 || fd >= PROG_MAX_FLOWS)
return -EBADF;
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
clock_gettime(PTHREAD_COND_CLOCK, &now);
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
if (flow->info.id < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return -ENOTALLOC;
}
if (flow->part_idx == DONE_PART) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
flow->part_idx = NO_PART;
return 0;
}
@@ -1467,7 +1477,7 @@ ssize_t flow_read(int fd,
idx = flow->part_idx;
if (idx < 0) {
while ((idx = frcti_queued_pdu(flow->frcti)) < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
idx = flow_rx_spb(flow, &spb, block, abstime);
if (idx < 0) {
@@ -1476,19 +1486,19 @@ ssize_t flow_read(int fd,
if (!block)
return idx;
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
continue;
}
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
frcti_rcv(flow->frcti, spb);
}
}
- spb = ssm_pool_get(ai.gspp, idx);
+ spb = ssm_pool_get(proc.pool, idx);
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
packet = ssm_pk_buff_head(spb);
@@ -1500,25 +1510,25 @@ ssize_t flow_read(int fd,
memcpy(buf, packet, n);
ipcp_spb_release(spb);
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
flow->part_idx = (partrd && n == (ssize_t) count) ?
DONE_PART : NO_PART;
flow->rcv_act = now;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return n;
} else {
if (partrd) {
memcpy(buf, packet, count);
ssm_pk_buff_head_release(spb, n);
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
flow->part_idx = idx;
flow->rcv_act = now;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return count;
} else {
ipcp_spb_release(spb);
@@ -1537,20 +1547,20 @@ struct flow_set * fset_create(void)
if (set == NULL)
goto fail_malloc;
- assert(ai.fqueues);
+ assert(proc.fqueues);
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
- set->idx = bmp_allocate(ai.fqueues);
- if (!bmp_is_id_valid(ai.fqueues, set->idx))
+ set->idx = bmp_allocate(proc.fqueues);
+ if (!bmp_is_id_valid(proc.fqueues, set->idx))
goto fail_bmp_alloc;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return set;
fail_bmp_alloc:
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
free(set);
fail_malloc:
return NULL;
@@ -1563,11 +1573,11 @@ void fset_destroy(struct flow_set * set)
fset_zero(set);
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
- bmp_release(ai.fqueues, set->idx);
+ bmp_release(proc.fqueues, set->idx);
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
free(set);
}
@@ -1595,7 +1605,7 @@ void fset_zero(struct flow_set * set)
if (set == NULL)
return;
- ssm_flow_set_zero(ai.fqset, set->idx);
+ ssm_flow_set_zero(proc.fqset, set->idx);
}
int fset_add(struct flow_set * set,
@@ -1607,9 +1617,9 @@ int fset_add(struct flow_set * set,
if (set == NULL || fd < 0 || fd >= SYS_MAX_FLOWS)
return -EINVAL;
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
if (flow->info.id < 0) {
ret = -EINVAL;
@@ -1617,21 +1627,21 @@ int fset_add(struct flow_set * set,
}
if (flow->frcti != NULL)
- ssm_flow_set_del(ai.fqset, 0, ai.flows[fd].info.id);
+ ssm_flow_set_del(proc.fqset, 0, flow->info.id);
- ret = ssm_flow_set_add(ai.fqset, set->idx, ai.flows[fd].info.id);
+ ret = ssm_flow_set_add(proc.fqset, set->idx, flow->info.id);
if (ret < 0)
goto fail;
- if (ssm_rbuff_queued(ai.flows[fd].rx_rb))
- ssm_flow_set_notify(ai.fqset, ai.flows[fd].info.id, FLOW_PKT);
+ if (ssm_rbuff_queued(flow->rx_rb))
+ ssm_flow_set_notify(proc.fqset, flow->info.id, FLOW_PKT);
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return ret;
fail:
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return ret;
}
@@ -1643,37 +1653,40 @@ void fset_del(struct flow_set * set,
if (set == NULL || fd < 0 || fd >= SYS_MAX_FLOWS)
return;
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
if (flow->info.id >= 0)
- ssm_flow_set_del(ai.fqset, set->idx, flow->info.id);
+ ssm_flow_set_del(proc.fqset, set->idx, flow->info.id);
if (flow->frcti != NULL)
- ssm_flow_set_add(ai.fqset, 0, ai.flows[fd].info.id);
+ ssm_flow_set_add(proc.fqset, 0, proc.flows[fd].info.id);
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
}
bool fset_has(const struct flow_set * set,
int fd)
{
- bool ret;
+ struct flow * flow;
+ bool ret;
if (set == NULL || fd < 0 || fd >= SYS_MAX_FLOWS)
return false;
- pthread_rwlock_rdlock(&ai.lock);
+ flow = &proc.flows[fd];
- if (ai.flows[fd].info.id < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
+
+ if (flow->info.id < 0) {
+ pthread_rwlock_unlock(&proc.lock);
return false;
}
- ret = (ssm_flow_set_has(ai.fqset, set->idx, ai.flows[fd].info.id) == 1);
+ ret = (ssm_flow_set_has(proc.fqset, set->idx, flow->info.id) == 1);
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return ret;
}
@@ -1690,44 +1703,44 @@ static int fqueue_filter(struct fqueue * fq)
if (fq->fqueue[fq->next].event != FLOW_PKT)
return 1;
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
- fd = ai.id_to_fd[fq->fqueue[fq->next].flow_id].fd;
+ fd = proc.id_to_fd[fq->fqueue[fq->next].flow_id].fd;
if (fd < 0) {
++fq->next;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
continue;
}
- frcti = ai.flows[fd].frcti;
+ frcti = proc.flows[fd].frcti;
if (frcti == NULL) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return 1;
}
if (__frcti_pdu_ready(frcti) >= 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return 1;
}
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
- idx = flow_rx_spb(&ai.flows[fd], &spb, false, NULL);
+ idx = flow_rx_spb(&proc.flows[fd], &spb, false, NULL);
if (idx < 0)
return 0;
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
- spb = ssm_pool_get(ai.gspp, idx);
+ spb = ssm_pool_get(proc.pool, idx);
__frcti_rcv(frcti, spb);
if (__frcti_pdu_ready(frcti) >= 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return 1;
}
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
++fq->next;
}
@@ -1749,15 +1762,15 @@ int fqueue_next(struct fqueue * fq)
if (fq->next != 0 && fqueue_filter(fq) == 0)
return -EPERM;
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
e = fq->fqueue + fq->next;
- fd = ai.id_to_fd[e->flow_id].fd;
+ fd = proc.id_to_fd[e->flow_id].fd;
++fq->next;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return fd;
}
@@ -1795,7 +1808,7 @@ ssize_t fevent(struct flow_set * set,
}
while (ret == 0) {
- ret = ssm_flow_set_wait(ai.fqset, set->idx, fq->fqueue, t);
+ ret = ssm_flow_set_wait(proc.fqset, set->idx, fq->fqueue, t);
if (ret == -ETIMEDOUT)
return -ETIMEDOUT;
@@ -1842,11 +1855,11 @@ int np1_flow_dealloc(int flow_id,
sleep(timeo);
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
- fd = ai.id_to_fd[flow_id].fd;
+ fd = proc.id_to_fd[flow_id].fd;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return fd;
}
@@ -1859,11 +1872,11 @@ int np1_flow_resp(int flow_id,
if (resp == 0 && flow_wait_assign(flow_id) != FLOW_ALLOCATED)
return -1;
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
- fd = ai.id_to_fd[flow_id].fd;
+ fd = proc.id_to_fd[flow_id].fd;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return fd;
}
@@ -1942,11 +1955,11 @@ int ipcp_flow_alloc_reply(int fd,
assert(fd >= 0 && fd < SYS_MAX_FLOWS);
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
- flow.id = ai.flows[fd].info.id;
+ flow.id = proc.flows[fd].info.id;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
flow.mpl = mpl;
@@ -1969,25 +1982,25 @@ int ipcp_flow_read(int fd,
assert(fd >= 0 && fd < SYS_MAX_FLOWS);
assert(spb);
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
assert(flow->info.id >= 0);
while (frcti_queued_pdu(flow->frcti) < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
idx = flow_rx_spb(flow, spb, false, NULL);
if (idx < 0)
return idx;
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
frcti_rcv(flow->frcti, *spb);
}
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return 0;
}
@@ -2001,88 +2014,132 @@ int ipcp_flow_write(int fd,
assert(fd >= 0 && fd < SYS_MAX_FLOWS);
assert(spb);
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&proc.lock);
if (flow->info.id < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return -ENOTALLOC;
}
if ((flow->oflags & FLOWFACCMODE) == FLOWFRDONLY) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return -EPERM;
}
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
ret = flow_tx_spb(flow, spb, true, NULL);
return ret;
}
+static int pool_copy_spb(struct ssm_pool * src_pool,
+ ssize_t src_idx,
+ struct ssm_pool * dst_pool,
+ struct ssm_pk_buff ** dst_spb)
+{
+ struct ssm_pk_buff * src;
+ uint8_t * ptr;
+ size_t len;
+
+ src = ssm_pool_get(src_pool, src_idx);
+ len = ssm_pk_buff_len(src);
+
+ if (ssm_pool_alloc(dst_pool, len, &ptr, dst_spb) < 0) {
+ ssm_pool_remove(src_pool, src_idx);
+ return -ENOMEM;
+ }
+
+ memcpy(ptr, ssm_pk_buff_head(src), len);
+ ssm_pool_remove(src_pool, src_idx);
+
+ return 0;
+}
+
int np1_flow_read(int fd,
- struct ssm_pk_buff ** spb)
+ struct ssm_pk_buff ** spb,
+ struct ssm_pool * pool)
{
- struct flow * flow;
- ssize_t idx = -1;
+ struct flow * flow;
+ ssize_t idx = -1;
assert(fd >= 0 && fd < SYS_MAX_FLOWS);
assert(spb);
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
assert(flow->info.id >= 0);
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
idx = ssm_rbuff_read(flow->rx_rb);
if (idx < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return idx;
}
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
- *spb = ssm_pool_get(ai.gspp, idx);
+ if (pool == NULL) {
+ *spb = ssm_pool_get(proc.pool, idx);
+ } else {
+ /* Cross-pool copy: PUP -> GSPP */
+ if (pool_copy_spb(pool, idx, proc.pool, spb) < 0)
+ return -ENOMEM;
+ }
return 0;
}
int np1_flow_write(int fd,
- struct ssm_pk_buff * spb)
+ struct ssm_pk_buff * spb,
+ struct ssm_pool * pool)
{
- struct flow * flow;
- int ret;
- ssize_t idx;
+ struct flow * flow;
+ struct ssm_pk_buff * dst;
+ int ret;
+ ssize_t idx;
assert(fd >= 0 && fd < SYS_MAX_FLOWS);
assert(spb);
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
if (flow->info.id < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return -ENOTALLOC;
}
if ((flow->oflags & FLOWFACCMODE) == FLOWFRDONLY) {
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return -EPERM;
}
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
idx = ssm_pk_buff_get_idx(spb);
- ret = ssm_rbuff_write_b(flow->tx_rb, idx, NULL);
- if (ret < 0)
- ssm_pool_remove(ai.gspp, idx);
- else
- ssm_flow_set_notify(flow->set, flow->info.id, FLOW_PKT);
+ if (pool == NULL) {
+ ret = ssm_rbuff_write_b(flow->tx_rb, idx, NULL);
+ if (ret < 0)
+ ssm_pool_remove(proc.pool, idx);
+ else
+ ssm_flow_set_notify(flow->set, flow->info.id, FLOW_PKT);
+ } else {
+ /* Cross-pool copy: GSPP -> PUP */
+ if (pool_copy_spb(proc.pool, idx, pool, &dst) < 0)
+ return -ENOMEM;
+ idx = ssm_pk_buff_get_idx(dst);
+ ret = ssm_rbuff_write_b(flow->tx_rb, idx, NULL);
+ if (ret < 0)
+ ssm_pool_remove(pool, idx);
+ else
+ ssm_flow_set_notify(flow->set, flow->info.id, FLOW_PKT);
+ }
return ret;
}
@@ -2090,12 +2147,12 @@ int np1_flow_write(int fd,
int ipcp_spb_reserve(struct ssm_pk_buff ** spb,
size_t len)
{
- return ssm_pool_alloc_b(ai.gspp, len, NULL, spb, NULL) < 0 ? -1 : 0;
+ return ssm_pool_alloc_b(proc.pool, len, NULL, spb, NULL) < 0 ? -1 : 0;
}
void ipcp_spb_release(struct ssm_pk_buff * spb)
{
- ssm_pool_remove(ai.gspp, ssm_pk_buff_get_idx(spb));
+ ssm_pool_remove(proc.pool, ssm_pk_buff_get_idx(spb));
}
int ipcp_flow_fini(int fd)
@@ -2104,23 +2161,23 @@ int ipcp_flow_fini(int fd)
assert(fd >= 0 && fd < SYS_MAX_FLOWS);
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
- if (ai.flows[fd].info.id < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ if (proc.flows[fd].info.id < 0) {
+ pthread_rwlock_unlock(&proc.lock);
return -1;
}
- ssm_rbuff_set_acl(ai.flows[fd].rx_rb, ACL_FLOWDOWN);
- ssm_rbuff_set_acl(ai.flows[fd].tx_rb, ACL_FLOWDOWN);
+ ssm_rbuff_set_acl(proc.flows[fd].rx_rb, ACL_FLOWDOWN);
+ ssm_rbuff_set_acl(proc.flows[fd].tx_rb, ACL_FLOWDOWN);
- ssm_flow_set_notify(ai.flows[fd].set,
- ai.flows[fd].info.id,
+ ssm_flow_set_notify(proc.flows[fd].set,
+ proc.flows[fd].info.id,
FLOW_DEALLOC);
- rx_rb = ai.flows[fd].rx_rb;
+ rx_rb = proc.flows[fd].rx_rb;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
if (rx_rb != NULL)
ssm_rbuff_fini(rx_rb);
@@ -2134,13 +2191,13 @@ int ipcp_flow_get_qoscube(int fd,
assert(fd >= 0 && fd < SYS_MAX_FLOWS);
assert(cube);
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
- assert(ai.flows[fd].info.id >= 0);
+ assert(proc.flows[fd].info.id >= 0);
- *cube = qos_spec_to_cube(ai.flows[fd].info.qs);
+ *cube = qos_spec_to_cube(proc.flows[fd].info.qs);
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return 0;
}
@@ -2149,56 +2206,76 @@ size_t ipcp_flow_queued(int fd)
{
size_t q;
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
- assert(ai.flows[fd].info.id >= 0);
+ assert(proc.flows[fd].info.id >= 0);
- q = ssm_rbuff_queued(ai.flows[fd].tx_rb);
+ q = ssm_rbuff_queued(proc.flows[fd].tx_rb);
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return q;
}
-ssize_t local_flow_read(int fd)
+int local_flow_transfer(int src_fd,
+ int dst_fd,
+ struct ssm_pool * src_pool,
+ struct ssm_pool * dst_pool)
{
- ssize_t ret;
-
- assert(fd >= 0);
+ struct flow * src_flow;
+ struct flow * dst_flow;
+ struct ssm_pk_buff * dst_spb;
+ struct ssm_pool * sp;
+ struct ssm_pool * dp;
+ ssize_t idx;
+ int ret;
- pthread_rwlock_rdlock(&ai.lock);
+ assert(src_fd >= 0);
+ assert(dst_fd >= 0);
- ret = ssm_rbuff_read(ai.flows[fd].rx_rb);
+ src_flow = &proc.flows[src_fd];
+ dst_flow = &proc.flows[dst_fd];
- pthread_rwlock_unlock(&ai.lock);
+ sp = src_pool == NULL ? proc.pool : src_pool;
+ dp = dst_pool == NULL ? proc.pool : dst_pool;
- return ret;
-}
-
-int local_flow_write(int fd,
- size_t idx)
-{
- struct flow * flow;
- int ret;
+ pthread_rwlock_rdlock(&proc.lock);
- assert(fd >= 0);
-
- flow = &ai.flows[fd];
-
- pthread_rwlock_rdlock(&ai.lock);
+ idx = ssm_rbuff_read(src_flow->rx_rb);
+ if (idx < 0) {
+ pthread_rwlock_unlock(&proc.lock);
+ return idx;
+ }
- if (flow->info.id < 0) {
- pthread_rwlock_unlock(&ai.lock);
+ if (dst_flow->info.id < 0) {
+ pthread_rwlock_unlock(&proc.lock);
+ ssm_pool_remove(sp, idx);
return -ENOTALLOC;
}
- ret = ssm_rbuff_write_b(flow->tx_rb, idx, NULL);
- if (ret == 0)
- ssm_flow_set_notify(flow->set, flow->info.id, FLOW_PKT);
- else
- ssm_pool_remove(ai.gspp, idx);
+ pthread_rwlock_unlock(&proc.lock);
+
+ if (sp == dp) {
+ /* Same pool: zero-copy */
+ ret = ssm_rbuff_write_b(dst_flow->tx_rb, idx, NULL);
+ if (ret < 0)
+ ssm_pool_remove(sp, idx);
+ else
+ ssm_flow_set_notify(dst_flow->set,
+ dst_flow->info.id, FLOW_PKT);
+ } else {
+ /* Different pools: single copy */
+ if (pool_copy_spb(sp, idx, dp, &dst_spb) < 0)
+ return -ENOMEM;
- pthread_rwlock_unlock(&ai.lock);
+ idx = ssm_pk_buff_get_idx(dst_spb);
+ ret = ssm_rbuff_write_b(dst_flow->tx_rb, idx, NULL);
+ if (ret < 0)
+ ssm_pool_remove(dp, idx);
+ else
+ ssm_flow_set_notify(dst_flow->set,
+ dst_flow->info.id, FLOW_PKT);
+ }
return ret;
}
diff --git a/src/lib/frct.c b/src/lib/frct.c
index 76736931..39a82966 100644
--- a/src/lib/frct.c
+++ b/src/lib/frct.c
@@ -118,11 +118,11 @@ static int frct_rib_read(const char * path,
fd = atoi(path);
- flow = &ai.flows[fd];
+ flow = &proc.flows[fd];
clock_gettime(PTHREAD_COND_CLOCK, &now);
- pthread_rwlock_rdlock(&ai.lock);
+ pthread_rwlock_rdlock(&proc.lock);
frcti = flow->frcti;
@@ -176,7 +176,7 @@ static int frct_rib_read(const char * path,
pthread_rwlock_unlock(&flow->frcti->lock);
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&proc.lock);
return strlen(buf);
}
@@ -244,9 +244,9 @@ static void __send_frct_pkt(int fd,
/* Raw calls needed to bypass frcti. */
#ifdef RXM_BLOCKING
- idx = ssm_pool_alloc_b(ai.gspp, sizeof(*pci), NULL, &spb, NULL);
+ idx = ssm_pool_alloc_b(proc.pool, sizeof(*pci), NULL, &spb, NULL);
#else
- idx = ssm_pool_alloc(ai.gspp, sizeof(*pci), NULL, &spb);
+ idx = ssm_pool_alloc(proc.pool, sizeof(*pci), NULL, &spb);
#endif
if (idx < 0)
return;
@@ -259,7 +259,7 @@ static void __send_frct_pkt(int fd,
pci->flags = flags;
pci->ackno = hton32(ackno);
- f = &ai.flows[fd];
+ f = &proc.flows[fd];
if (spb_encrypt(f, spb) < 0)
goto fail;
@@ -398,7 +398,7 @@ static struct frcti * frcti_create(int fd,
frcti->n_out = 0;
frcti->n_rqo = 0;
#endif
- if (ai.flows[fd].info.qs.loss == 0) {
+ if (proc.flows[fd].info.qs.loss == 0) {
frcti->snd_cr.cflags |= FRCTFRTX | FRCTFLINGER;
frcti->rcv_cr.cflags |= FRCTFRTX;
}
@@ -841,7 +841,7 @@ static void __frcti_rcv(struct frcti * frcti,
__send_frct_pkt(fd, FRCT_FC, 0, rwe);
- ssm_pool_remove(ai.gspp, idx);
+ ssm_pool_remove(proc.pool, idx);
return;
}
@@ -928,7 +928,7 @@ static void __frcti_rcv(struct frcti * frcti,
drop_packet:
pthread_rwlock_unlock(&frcti->lock);
- ssm_pool_remove(ai.gspp, idx);
+ ssm_pool_remove(proc.pool, idx);
send_frct_pkt(frcti);
return;
}
diff --git a/src/lib/pb/ipcp.proto b/src/lib/pb/ipcp.proto
index c2c7f48b..deddf6af 100644
--- a/src/lib/pb/ipcp.proto
+++ b/src/lib/pb/ipcp.proto
@@ -56,4 +56,5 @@ message ipcp_msg {
optional uint32 timeo_sec = 12;
optional sint32 mpl = 13;
optional int32 result = 14;
+ optional uint32 uid = 15; /* 0 = GSPP, >0 = PUP uid */
}
diff --git a/src/lib/pb/irm.proto b/src/lib/pb/irm.proto
index 5d0ee611..1845c694 100644
--- a/src/lib/pb/irm.proto
+++ b/src/lib/pb/irm.proto
@@ -94,6 +94,6 @@ message irm_msg {
optional uint32 timeo_sec = 23;
optional uint32 timeo_nsec = 24;
optional sint32 result = 25;
- optional bytes sym_key = 26; /* symmetric encryption key */
- optional sint32 cipher_nid = 27; /* cipher NID */
+ optional bytes sym_key = 26; /* symmetric encryption key */
+ optional sint32 cipher_nid = 27; /* cipher NID */
}
diff --git a/src/lib/pb/model.proto b/src/lib/pb/model.proto
index 7b06e434..82700a9a 100644
--- a/src/lib/pb/model.proto
+++ b/src/lib/pb/model.proto
@@ -34,12 +34,13 @@ message qosspec_msg {
}
message flow_info_msg {
- required uint32 id = 1;
- required uint32 n_pid = 2;
- required uint32 n_1_pid = 3;
- required uint32 mpl = 4;
- required uint32 state = 5;
- required qosspec_msg qos = 6;
+ required uint32 id = 1;
+ required uint32 n_pid = 2;
+ required uint32 n_1_pid = 3;
+ required uint32 mpl = 4;
+ required uint32 state = 5;
+ required qosspec_msg qos = 6;
+ required uint32 uid = 7;
}
message name_info_msg {
diff --git a/src/lib/protobuf.c b/src/lib/protobuf.c
index bd6c179e..4617323a 100644
--- a/src/lib/protobuf.c
+++ b/src/lib/protobuf.c
@@ -24,6 +24,7 @@
#include <ouroboros/protobuf.h>
#include <ouroboros/crypt.h>
+#include <ouroboros/proc.h>
#include <stdlib.h>
#include <string.h>
@@ -74,12 +75,13 @@ flow_info_msg_t * flow_info_s_to_msg(const struct flow_info * s)
flow_info_msg__init(msg);
- msg->id = s->id;
- msg->n_pid = s->n_pid;
- msg->n_1_pid = s->n_1_pid;
- msg->mpl = s->mpl;
- msg->state = s->state;
- msg->qos = qos_spec_s_to_msg(&s->qs);
+ msg->id = s->id;
+ msg->n_pid = s->n_pid;
+ msg->n_1_pid = s->n_1_pid;
+ msg->mpl = s->mpl;
+ msg->state = s->state;
+ msg->uid = s->uid;
+ msg->qos = qos_spec_s_to_msg(&s->qs);
if (msg->qos == NULL)
goto fail_msg;
@@ -104,6 +106,7 @@ struct flow_info flow_info_msg_to_s(const flow_info_msg_t * msg)
s.n_1_pid = msg->n_1_pid;
s.mpl = msg->mpl;
s.state = msg->state;
+ s.uid = msg->uid;
s.qs = qos_spec_msg_to_s(msg->qos);
return s;
diff --git a/src/lib/serdes-irm.c b/src/lib/serdes-irm.c
index 9e829632..8cbe20b1 100644
--- a/src/lib/serdes-irm.c
+++ b/src/lib/serdes-irm.c
@@ -289,8 +289,8 @@ int ipcp_create_r__irm_req_ser(buffer_t * buf,
return -ENOMEM;
}
-int proc_announce__irm_req_ser(buffer_t * buf,
- const char * prog)
+int proc_announce__irm_req_ser(buffer_t * buf,
+ const struct proc_info * proc)
{
irm_msg_t * msg;
size_t len;
@@ -303,8 +303,8 @@ int proc_announce__irm_req_ser(buffer_t * buf,
msg->code = IRM_MSG_CODE__IRM_PROC_ANNOUNCE;
msg->has_pid = true;
- msg->pid = getpid();
- msg->prog = strdup(prog);
+ msg->pid = proc->pid;
+ msg->prog = strdup(proc->prog);
if (msg->prog == NULL)
goto fail_msg;
diff --git a/src/lib/ssm/pool.c b/src/lib/ssm/pool.c
index b8cfe3a1..e938f644 100644
--- a/src/lib/ssm/pool.c
+++ b/src/lib/ssm/pool.c
@@ -41,17 +41,30 @@
#include <sys/mman.h>
#include <sys/stat.h>
-/* Size class configuration from CMake */
-static const struct ssm_size_class_cfg ssm_sc_cfg[SSM_POOL_MAX_CLASSES] = {
- { (1 << 8), SSM_POOL_256_BLOCKS },
- { (1 << 9), SSM_POOL_512_BLOCKS },
- { (1 << 10), SSM_POOL_1K_BLOCKS },
- { (1 << 11), SSM_POOL_2K_BLOCKS },
- { (1 << 12), SSM_POOL_4K_BLOCKS },
- { (1 << 14), SSM_POOL_16K_BLOCKS },
- { (1 << 16), SSM_POOL_64K_BLOCKS },
- { (1 << 18), SSM_POOL_256K_BLOCKS },
- { (1 << 20), SSM_POOL_1M_BLOCKS },
+/* Global Shared Packet Pool (GSPP) configuration */
+static const struct ssm_size_class_cfg ssm_gspp_cfg[SSM_POOL_MAX_CLASSES] = {
+ { (1 << 8), SSM_GSPP_256_BLOCKS },
+ { (1 << 9), SSM_GSPP_512_BLOCKS },
+ { (1 << 10), SSM_GSPP_1K_BLOCKS },
+ { (1 << 11), SSM_GSPP_2K_BLOCKS },
+ { (1 << 12), SSM_GSPP_4K_BLOCKS },
+ { (1 << 14), SSM_GSPP_16K_BLOCKS },
+ { (1 << 16), SSM_GSPP_64K_BLOCKS },
+ { (1 << 18), SSM_GSPP_256K_BLOCKS },
+ { (1 << 20), SSM_GSPP_1M_BLOCKS },
+};
+
+/* Per-User Pool (PUP) configuration */
+static const struct ssm_size_class_cfg ssm_pup_cfg[SSM_POOL_MAX_CLASSES] = {
+ { (1 << 8), SSM_PUP_256_BLOCKS },
+ { (1 << 9), SSM_PUP_512_BLOCKS },
+ { (1 << 10), SSM_PUP_1K_BLOCKS },
+ { (1 << 11), SSM_PUP_2K_BLOCKS },
+ { (1 << 12), SSM_PUP_4K_BLOCKS },
+ { (1 << 14), SSM_PUP_16K_BLOCKS },
+ { (1 << 16), SSM_PUP_64K_BLOCKS },
+ { (1 << 18), SSM_PUP_256K_BLOCKS },
+ { (1 << 20), SSM_PUP_1M_BLOCKS },
};
#define PTR_TO_OFFSET(pool_base, ptr) \
@@ -83,16 +96,23 @@ static const struct ssm_size_class_cfg ssm_sc_cfg[SSM_POOL_MAX_CLASSES] = {
#define FETCH_SUB(ptr, val) \
(__atomic_fetch_sub(ptr, val, __ATOMIC_SEQ_CST))
-#define CAS(ptr, expected, desired) \
- (__atomic_compare_exchange_n(ptr, expected, desired, false, \
- __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
-
#define SSM_FILE_SIZE (SSM_POOL_TOTAL_SIZE + sizeof(struct _ssm_pool_hdr))
+#define SSM_GSPP_FILE_SIZE (SSM_GSPP_TOTAL_SIZE + sizeof(struct _ssm_pool_hdr))
+#define SSM_PUP_FILE_SIZE (SSM_PUP_TOTAL_SIZE + sizeof(struct _ssm_pool_hdr))
+
+#define IS_GSPP(uid) ((uid) == SSM_GSPP_UID)
+#define GET_POOL_TOTAL_SIZE(uid) (IS_GSPP(uid) ? SSM_GSPP_TOTAL_SIZE \
+ : SSM_PUP_TOTAL_SIZE)
+#define GET_POOL_FILE_SIZE(uid) (IS_GSPP(uid) ? SSM_GSPP_FILE_SIZE \
+ : SSM_PUP_FILE_SIZE)
+#define GET_POOL_CFG(uid) (IS_GSPP(uid) ? ssm_gspp_cfg : ssm_pup_cfg)
struct ssm_pool {
- uint8_t * shm_base; /* start of blocks */
- struct _ssm_pool_hdr * hdr; /* shared memory header */
- void * pool_base; /* base of the memory pool */
+ uint8_t * shm_base; /* start of blocks */
+ struct _ssm_pool_hdr * hdr; /* shared memory header */
+ void * pool_base; /* base of the memory pool */
+ uid_t uid; /* user owner (0 = GSPP) */
+ size_t total_size; /* total data size */
};
static __inline__
@@ -143,17 +163,23 @@ static __inline__ void list_add_head(struct _ssm_list_head * head,
STORE(&head->count, LOAD(&head->count) + 1);
}
-static __inline__ int select_size_class(size_t len)
+static __inline__ int select_size_class(struct ssm_pool * pool,
+ size_t len)
{
size_t sz;
int i;
+ assert(pool != NULL);
+
/* Total space needed: header + headspace + data + tailspace */
sz = sizeof(struct ssm_pk_buff) + SSM_PK_BUFF_HEADSPACE + len
+ SSM_PK_BUFF_TAILSPACE;
for (i = 0; i < SSM_POOL_MAX_CLASSES; i++) {
- if (ssm_sc_cfg[i].blocks > 0 && sz <= ssm_sc_cfg[i].size)
+ struct _ssm_size_class * sc;
+
+ sc = &pool->hdr->size_classes[i];
+ if (sc->object_size > 0 && sz <= sc->object_size)
return i;
}
@@ -183,15 +209,16 @@ static __inline__ int find_size_class_for_offset(struct ssm_pool * pool,
static void init_size_classes(struct ssm_pool * pool)
{
- struct _ssm_size_class * sc;
- struct _ssm_shard * shard;
- pthread_mutexattr_t mattr;
- pthread_condattr_t cattr;
- uint8_t * region;
- size_t offset;
- int c;
- int s;
- size_t i;
+ const struct ssm_size_class_cfg * cfg;
+ struct _ssm_size_class * sc;
+ struct _ssm_shard * shard;
+ pthread_mutexattr_t mattr;
+ pthread_condattr_t cattr;
+ uint8_t * region;
+ size_t offset;
+ int c; /* class iterator */
+ int s; /* shard iterator */
+ size_t i;
assert(pool != NULL);
@@ -199,6 +226,8 @@ static void init_size_classes(struct ssm_pool * pool)
if (LOAD(&pool->hdr->initialized) != 0)
return;
+ cfg = GET_POOL_CFG(pool->uid);
+
pthread_mutexattr_init(&mattr);
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
#ifdef HAVE_ROBUST_MUTEX
@@ -214,15 +243,15 @@ static void init_size_classes(struct ssm_pool * pool)
offset = 0;
for (c = 0; c < SSM_POOL_MAX_CLASSES; c++) {
- if (ssm_sc_cfg[c].blocks == 0)
+ if (cfg[c].blocks == 0)
continue;
sc = &pool->hdr->size_classes[c];
- sc->object_size = ssm_sc_cfg[c].size;
+ sc->object_size = cfg[c].size;
sc->pool_start = offset;
- sc->pool_size = ssm_sc_cfg[c].size * ssm_sc_cfg[c].blocks;
- sc->object_count = ssm_sc_cfg[c].blocks;
+ sc->pool_size = cfg[c].size * cfg[c].blocks;
+ sc->object_count = cfg[c].blocks;
/* Initialize all shards */
for (s = 0; s < SSM_POOL_SHARDS; s++) {
@@ -444,23 +473,26 @@ static ssize_t alloc_from_sc_b(struct ssm_pool * pool,
return init_block(pool, sc, shard, blk, len, ptr, spb);
}
-/* Global Shared Packet Pool */
-static char * gspp_filename(void)
+/* Generate pool filename: uid=0 for GSPP, uid>0 for PUP */
+static char * pool_filename(uid_t uid)
{
char * str;
char * test_suffix;
+ char base[64];
+
+ if (IS_GSPP(uid))
+ snprintf(base, sizeof(base), "%s", SSM_GSPP_NAME);
+ else
+ snprintf(base, sizeof(base), SSM_PUP_NAME_FMT, (int) uid);
test_suffix = getenv("OUROBOROS_TEST_POOL_SUFFIX");
if (test_suffix != NULL) {
- str = malloc(strlen(SSM_POOL_NAME) + strlen(test_suffix) + 1);
+ str = malloc(strlen(base) + strlen(test_suffix) + 1);
if (str == NULL)
return NULL;
- sprintf(str, "%s%s", SSM_POOL_NAME, test_suffix);
+ sprintf(str, "%s%s", base, test_suffix);
} else {
- str = malloc(strlen(SSM_POOL_NAME) + 1);
- if (str == NULL)
- return NULL;
- sprintf(str, "%s", SSM_POOL_NAME);
+ str = strdup(base);
}
return str;
@@ -468,9 +500,13 @@ static char * gspp_filename(void)
void ssm_pool_close(struct ssm_pool * pool)
{
+ size_t file_size;
+
assert(pool != NULL);
- munmap(pool->shm_base, SSM_FILE_SIZE);
+ file_size = GET_POOL_FILE_SIZE(pool->uid);
+
+ munmap(pool->shm_base, file_size);
free(pool);
}
@@ -481,15 +517,19 @@ void ssm_pool_destroy(struct ssm_pool * pool)
assert(pool != NULL);
if (getpid() != pool->hdr->pid && kill(pool->hdr->pid, 0) == 0) {
+ ssm_pool_close(pool);
free(pool);
return;
}
- ssm_pool_close(pool);
-
- fn = gspp_filename();
- if (fn == NULL)
+ fn = pool_filename(pool->uid);
+ if (fn == NULL) {
+ ssm_pool_close(pool);
+ free(pool);
return;
+ }
+
+ ssm_pool_close(pool);
shm_unlink(fn);
free(fn);
@@ -497,72 +537,89 @@ void ssm_pool_destroy(struct ssm_pool * pool)
#define MM_FLAGS (PROT_READ | PROT_WRITE)
-static struct ssm_pool * pool_create(int flags)
+static struct ssm_pool * __pool_create(const char * name,
+ int flags,
+ uid_t uid,
+ mode_t mode)
{
struct ssm_pool * pool;
int fd;
uint8_t * shm_base;
- char * fn;
+ size_t file_size;
+ size_t total_size;
- fn = gspp_filename();
- if (fn == NULL)
- goto fail_fn;
+ file_size = GET_POOL_FILE_SIZE(uid);
+ total_size = GET_POOL_TOTAL_SIZE(uid);
- pool = malloc(sizeof *pool);
+ pool = malloc(sizeof(*pool));
if (pool == NULL)
- goto fail_rdrb;
+ goto fail_pool;
- fd = shm_open(fn, flags, 0666);
+ fd = shm_open(name, flags, mode);
if (fd == -1)
goto fail_open;
- if ((flags & O_CREAT) && ftruncate(fd, SSM_FILE_SIZE) < 0)
+ if ((flags & O_CREAT) && ftruncate(fd, (off_t) file_size) < 0)
goto fail_truncate;
- shm_base = mmap(NULL, SSM_FILE_SIZE, MM_FLAGS, MAP_SHARED, fd, 0);
+ shm_base = mmap(NULL, file_size, MM_FLAGS, MAP_SHARED, fd, 0);
if (shm_base == MAP_FAILED)
goto fail_truncate;
- pool->shm_base = shm_base;
- pool->pool_base = shm_base;
- pool->hdr = (struct _ssm_pool_hdr *) (shm_base + SSM_POOL_TOTAL_SIZE);
+ pool->shm_base = shm_base;
+ pool->pool_base = shm_base;
+ pool->hdr = (struct _ssm_pool_hdr *) (shm_base + total_size);
+ pool->uid = uid;
+ pool->total_size = total_size;
if (flags & O_CREAT)
pool->hdr->mapped_addr = shm_base;
close(fd);
- free(fn);
-
return pool;
fail_truncate:
close(fd);
if (flags & O_CREAT)
- shm_unlink(fn);
+ shm_unlink(name);
fail_open:
free(pool);
- fail_rdrb:
- free(fn);
- fail_fn:
+ fail_pool:
return NULL;
}
-struct ssm_pool * ssm_pool_create(void)
+struct ssm_pool * ssm_pool_create(uid_t uid,
+ gid_t gid)
{
struct ssm_pool * pool;
+ char * fn;
mode_t mask;
+ mode_t mode;
pthread_mutexattr_t mattr;
pthread_condattr_t cattr;
+ int fd;
+ fn = pool_filename(uid);
+ if (fn == NULL)
+ goto fail_fn;
+
+ mode = IS_GSPP(uid) ? 0660 : 0600;
mask = umask(0);
- pool = pool_create(O_CREAT | O_EXCL | O_RDWR);
+ pool = __pool_create(fn, O_CREAT | O_EXCL | O_RDWR, uid, mode);
umask(mask);
if (pool == NULL)
- goto fail_rdrb;
+ goto fail_pool;
+
+ fd = shm_open(fn, O_RDWR, 0);
+ if (fd >= 0) {
+ fchown(fd, uid, gid);
+ fchmod(fd, mode);
+ close(fd);
+ }
if (pthread_mutexattr_init(&mattr))
goto fail_mattr;
@@ -585,13 +642,13 @@ struct ssm_pool * ssm_pool_create(void)
goto fail_healthy;
pool->hdr->pid = getpid();
- /* Will be set by init_size_classes */
STORE(&pool->hdr->initialized, 0);
init_size_classes(pool);
pthread_mutexattr_destroy(&mattr);
pthread_condattr_destroy(&cattr);
+ free(fn);
return pool;
@@ -602,27 +659,37 @@ struct ssm_pool * ssm_pool_create(void)
fail_mutex:
pthread_mutexattr_destroy(&mattr);
fail_mattr:
- ssm_pool_destroy(pool);
- fail_rdrb:
+ ssm_pool_close(pool);
+ shm_unlink(fn);
+ fail_pool:
+ free(fn);
+ fail_fn:
return NULL;
}
-struct ssm_pool * ssm_pool_open(void)
+struct ssm_pool * ssm_pool_open(uid_t uid)
{
struct ssm_pool * pool;
+ char * fn;
+
+ fn = pool_filename(uid);
+ if (fn == NULL)
+ return NULL;
- pool = pool_create(O_RDWR);
+ pool = __pool_create(fn, O_RDWR, uid, 0);
if (pool != NULL)
init_size_classes(pool);
+ free(fn);
+
return pool;
}
-void ssm_pool_purge(void)
+void ssm_pool_gspp_purge(void)
{
char * fn;
- fn = gspp_filename();
+ fn = pool_filename(SSM_GSPP_UID);
if (fn == NULL)
return;
@@ -632,9 +699,13 @@ void ssm_pool_purge(void)
int ssm_pool_mlock(struct ssm_pool * pool)
{
+ size_t file_size;
+
assert(pool != NULL);
- return mlock(pool->shm_base, SSM_FILE_SIZE);
+ file_size = GET_POOL_FILE_SIZE(pool->uid);
+
+ return mlock(pool->shm_base, file_size);
}
ssize_t ssm_pool_alloc(struct ssm_pool * pool,
@@ -647,7 +718,7 @@ ssize_t ssm_pool_alloc(struct ssm_pool * pool,
assert(pool != NULL);
assert(spb != NULL);
- idx = select_size_class(count);
+ idx = select_size_class(pool, count);
if (idx >= 0)
return alloc_from_sc(pool, idx, count, ptr, spb);
@@ -665,7 +736,7 @@ ssize_t ssm_pool_alloc_b(struct ssm_pool * pool,
assert(pool != NULL);
assert(spb != NULL);
- idx = select_size_class(count);
+ idx = select_size_class(pool, count);
if (idx >= 0)
return alloc_from_sc_b(pool, idx, count, ptr, spb, abstime);
@@ -697,7 +768,7 @@ struct ssm_pk_buff * ssm_pool_get(struct ssm_pool * pool,
assert(pool != NULL);
- if (off == 0 || off >= (size_t) SSM_POOL_TOTAL_SIZE)
+ if (off == 0 || off >= pool->total_size)
return NULL;
blk = OFFSET_TO_PTR(pool->pool_base, off);
@@ -722,7 +793,7 @@ int ssm_pool_remove(struct ssm_pool * pool,
assert(pool != NULL);
- if (off == 0 || off >= SSM_POOL_TOTAL_SIZE)
+ if (off == 0 || off >= pool->total_size)
return -EINVAL;
blk = OFFSET_TO_PTR(pool->pool_base, off);
diff --git a/src/lib/ssm/ssm.h.in b/src/lib/ssm/ssm.h.in
index d14cd49c..b9246c8b 100644
--- a/src/lib/ssm/ssm.h.in
+++ b/src/lib/ssm/ssm.h.in
@@ -30,8 +30,9 @@
/* Pool naming configuration */
#define SSM_PREFIX "@SSM_PREFIX@"
-#define SSM_GSMP_SUFFIX "@SSM_GSMP_SUFFIX@"
-#define SSM_PPP_SUFFIX "@SSM_PPP_SUFFIX@"
+#define SSM_GSPP_NAME "@SSM_GSPP_NAME@"
+#define SSM_PUP_NAME_FMT "@SSM_PUP_NAME_FMT@"
+#define SSM_GSPP_UID 0
/* Legacy SSM constants */
#define SSM_RBUFF_PREFIX "@SSM_RBUFF_PREFIX@"
@@ -44,7 +45,31 @@
#define SSM_PK_BUFF_HEADSPACE @SSM_PK_BUFF_HEADSPACE@
#define SSM_PK_BUFF_TAILSPACE @SSM_PK_BUFF_TAILSPACE@
-/* Pool blocks per size class */
+/* Global Shared Packet Pool (GSPP) - for privileged processes */
+#define SSM_GSPP_256_BLOCKS @SSM_GSPP_256_BLOCKS@
+#define SSM_GSPP_512_BLOCKS @SSM_GSPP_512_BLOCKS@
+#define SSM_GSPP_1K_BLOCKS @SSM_GSPP_1K_BLOCKS@
+#define SSM_GSPP_2K_BLOCKS @SSM_GSPP_2K_BLOCKS@
+#define SSM_GSPP_4K_BLOCKS @SSM_GSPP_4K_BLOCKS@
+#define SSM_GSPP_16K_BLOCKS @SSM_GSPP_16K_BLOCKS@
+#define SSM_GSPP_64K_BLOCKS @SSM_GSPP_64K_BLOCKS@
+#define SSM_GSPP_256K_BLOCKS @SSM_GSPP_256K_BLOCKS@
+#define SSM_GSPP_1M_BLOCKS @SSM_GSPP_1M_BLOCKS@
+#define SSM_GSPP_TOTAL_SIZE @SSM_GSPP_TOTAL_SIZE@
+
+/* Per-User Pool (PUP) - for unprivileged applications */
+#define SSM_PUP_256_BLOCKS @SSM_PUP_256_BLOCKS@
+#define SSM_PUP_512_BLOCKS @SSM_PUP_512_BLOCKS@
+#define SSM_PUP_1K_BLOCKS @SSM_PUP_1K_BLOCKS@
+#define SSM_PUP_2K_BLOCKS @SSM_PUP_2K_BLOCKS@
+#define SSM_PUP_4K_BLOCKS @SSM_PUP_4K_BLOCKS@
+#define SSM_PUP_16K_BLOCKS @SSM_PUP_16K_BLOCKS@
+#define SSM_PUP_64K_BLOCKS @SSM_PUP_64K_BLOCKS@
+#define SSM_PUP_256K_BLOCKS @SSM_PUP_256K_BLOCKS@
+#define SSM_PUP_1M_BLOCKS @SSM_PUP_1M_BLOCKS@
+#define SSM_PUP_TOTAL_SIZE @SSM_PUP_TOTAL_SIZE@
+
+/* Legacy pool blocks (same as GSPP for compatibility) */
#define SSM_POOL_256_BLOCKS @SSM_POOL_256_BLOCKS@
#define SSM_POOL_512_BLOCKS @SSM_POOL_512_BLOCKS@
#define SSM_POOL_1K_BLOCKS @SSM_POOL_1K_BLOCKS@
diff --git a/src/lib/ssm/tests/CMakeLists.txt b/src/lib/ssm/tests/CMakeLists.txt
index 827f8bf8..5cac70d1 100644
--- a/src/lib/ssm/tests/CMakeLists.txt
+++ b/src/lib/ssm/tests/CMakeLists.txt
@@ -18,16 +18,5 @@ target_link_libraries(${PARENT_DIR}_test ouroboros-common)
add_dependencies(build_tests ${PARENT_DIR}_test)
-set(tests_to_run ${${PARENT_DIR}_tests})
-if(CMAKE_VERSION VERSION_LESS "3.29.0")
- remove(tests_to_run test_suite.c)
-else ()
- list(POP_FRONT tests_to_run)
-endif()
-
-foreach (test ${tests_to_run})
- get_filename_component(test_name ${test} NAME_WE)
- add_test(${TEST_PREFIX}/${test_name} ${C_TEST_PATH}/${PARENT_DIR}_test ${test_name})
- set_property(TEST ${TEST_PREFIX}/${test_name}
- PROPERTY ENVIRONMENT "OUROBOROS_TEST_POOL_SUFFIX=.test")
-endforeach (test)
+ouroboros_register_tests(TARGET ${PARENT_DIR}_test TESTS ${${PARENT_DIR}_tests}
+ ENVIRONMENT "OUROBOROS_TEST_POOL_SUFFIX=.test")
diff --git a/src/lib/ssm/tests/pool_sharding_test.c b/src/lib/ssm/tests/pool_sharding_test.c
index 72ae1cb7..46eecd8d 100644
--- a/src/lib/ssm/tests/pool_sharding_test.c
+++ b/src/lib/ssm/tests/pool_sharding_test.c
@@ -54,6 +54,7 @@ static struct _ssm_pool_hdr * get_pool_hdr(struct ssm_pool * pool)
*/
struct _ssm_pool_hdr ** hdr_ptr =
(struct _ssm_pool_hdr **)((uint8_t *)pool + sizeof(void *));
+
return *hdr_ptr;
}
@@ -67,9 +68,7 @@ static int test_lazy_distribution(void)
TEST_START();
- ssm_pool_purge();
-
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL) {
printf("Failed to create pool.\n");
goto fail;
@@ -142,9 +141,7 @@ static int test_shard_migration(void)
TEST_START();
- ssm_pool_purge();
-
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL) {
printf("Failed to create pool.\n");
goto fail;
@@ -216,9 +213,7 @@ static int test_fallback_stealing(void)
TEST_START();
- ssm_pool_purge();
-
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL) {
printf("Failed to create pool.\n");
goto fail;
@@ -331,9 +326,7 @@ static int test_multiprocess_sharding(void)
TEST_START();
- ssm_pool_purge();
-
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL) {
printf("Failed to create pool.\n");
goto fail;
@@ -355,7 +348,7 @@ static int test_multiprocess_sharding(void)
ssize_t off;
int my_shard;
- child_pool = ssm_pool_open();
+ child_pool = ssm_pool_open(0);
if (child_pool == NULL)
exit(EXIT_FAILURE);
@@ -449,9 +442,7 @@ static int test_exhaustion_with_fallback(void)
TEST_START();
- ssm_pool_purge();
-
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL) {
printf("Failed to create pool.\n");
goto fail;
diff --git a/src/lib/ssm/tests/pool_test.c b/src/lib/ssm/tests/pool_test.c
index e298d9ab..53f7f541 100644
--- a/src/lib/ssm/tests/pool_test.c
+++ b/src/lib/ssm/tests/pool_test.c
@@ -61,7 +61,7 @@ static int test_ssm_pool_basic_allocation(void)
TEST_START();
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -119,7 +119,7 @@ static int test_ssm_pool_multiple_allocations(void)
TEST_START();
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -212,7 +212,7 @@ static int test_ssm_pool_no_fallback_for_large(void)
TEST_START();
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -248,7 +248,7 @@ static int test_ssm_pool_blocking_vs_nonblocking(void)
TEST_START();
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -295,7 +295,7 @@ static int test_ssm_pool_stress_test(void)
TEST_START();
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -392,7 +392,7 @@ static int test_ssm_pool_open_initializes_ssm(void)
TEST_START();
- creator = ssm_pool_create();
+ creator = ssm_pool_create(0, getgid());
if (creator == NULL)
goto fail_create;
@@ -403,7 +403,7 @@ static int test_ssm_pool_open_initializes_ssm(void)
}
ssm_pool_remove(creator, ret);
- opener = ssm_pool_open();
+ opener = ssm_pool_open(0);
if (opener == NULL) {
printf("Open failed.\n");
goto fail_creator;
@@ -439,7 +439,7 @@ static int test_ssm_pool_bounds_checking(void)
TEST_START();
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -502,7 +502,7 @@ static int test_ssm_pool_inter_process_communication(void)
len = strlen(msg) + 1;
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -606,7 +606,7 @@ static int test_ssm_pool_read_operation(void)
len = strlen(data) + 1;
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -656,7 +656,7 @@ static int test_ssm_pool_mlock_operation(void)
TEST_START();
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -690,7 +690,7 @@ static int test_ssm_pk_buff_operations(void)
dlen = strlen(data);
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -798,7 +798,7 @@ static int test_ssm_pool_size_class_boundaries(void)
TEST_START();
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -859,7 +859,7 @@ static int test_ssm_pool_exhaustion(void)
TEST_START();
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -937,7 +937,7 @@ static int test_ssm_pool_reclaim_orphans(void)
TEST_START();
- pool = ssm_pool_create();
+ pool = ssm_pool_create(0, getgid());
if (pool == NULL)
goto fail_create;
@@ -1017,8 +1017,6 @@ int pool_test(int argc,
(void) argc;
(void) argv;
- ssm_pool_purge();
-
ret |= test_ssm_pool_basic_allocation();
ret |= test_ssm_pool_multiple_allocations();
ret |= test_ssm_pool_no_fallback_for_large();
diff --git a/src/lib/tests/CMakeLists.txt b/src/lib/tests/CMakeLists.txt
index d2535bc2..23d01f9b 100644
--- a/src/lib/tests/CMakeLists.txt
+++ b/src/lib/tests/CMakeLists.txt
@@ -28,20 +28,4 @@ target_link_libraries(${PARENT_DIR}_test ouroboros-common)
add_dependencies(build_tests ${PARENT_DIR}_test)
-set(tests_to_run ${${PARENT_DIR}_tests})
-if(CMAKE_VERSION VERSION_LESS "3.29.0")
- remove(tests_to_run test_suite.c)
-else ()
- list(POP_FRONT tests_to_run)
-endif()
-
-foreach (test ${tests_to_run})
- get_filename_component(test_name ${test} NAME_WE)
- add_test(${TEST_PREFIX}/${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${PARENT_DIR}_test ${test_name})
-endforeach (test)
-
-set_property(TEST ${TEST_PREFIX}/auth_test PROPERTY SKIP_RETURN_CODE 1)
-set_property(TEST ${TEST_PREFIX}/auth_test_pqc PROPERTY SKIP_RETURN_CODE 1)
-set_property(TEST ${TEST_PREFIX}/crypt_test PROPERTY SKIP_RETURN_CODE 1)
-set_property(TEST ${TEST_PREFIX}/kex_test PROPERTY SKIP_RETURN_CODE 1)
-set_property(TEST ${TEST_PREFIX}/kex_test_pqc PROPERTY SKIP_RETURN_CODE 1)
+ouroboros_register_tests(TARGET ${PARENT_DIR}_test TESTS ${${PARENT_DIR}_tests})
diff --git a/src/lib/timerwheel.c b/src/lib/timerwheel.c
index eaa684e5..ed235047 100644
--- a/src/lib/timerwheel.c
+++ b/src/lib/timerwheel.c
@@ -173,7 +173,7 @@ static void timerwheel_move(void)
snd_cr = &r->frcti->snd_cr;
rcv_cr = &r->frcti->rcv_cr;
- f = &ai.flows[r->fd];
+ f = &proc.flows[r->fd];
#ifndef RXM_BUFFER_ON_HEAP
ssm_pk_buff_ack(r->spb);
#endif
@@ -226,7 +226,7 @@ static void timerwheel_move(void)
#ifdef RXM_BLOCKING
if (ipcp_spb_reserve(&spb, r->len) < 0)
#else
- if (ssm_pool_alloc(ai.gspp, r->len, NULL,
+ if (ssm_pool_alloc(proc.pool, r->len, NULL,
&spb) < 0)
#endif
goto reschedule; /* rdrbuff full */
@@ -288,7 +288,7 @@ static void timerwheel_move(void)
list_del(&a->next);
- f = &ai.flows[a->fd];
+ f = &proc.flows[a->fd];
rw.map[j & (ACKQ_SLOTS - 1)][a->fd] = false;
@@ -341,7 +341,7 @@ static int timerwheel_rxm(struct frcti * frcti,
slot = r->t0 >> RXMQ_RES;
r->fd = frcti->fd;
- r->flow_id = ai.flows[r->fd].info.id;
+ r->flow_id = proc.flows[r->fd].info.id;
pthread_rwlock_unlock(&r->frcti->lock);
@@ -394,7 +394,7 @@ static int timerwheel_delayed_ack(int fd,
a->fd = fd;
a->frcti = frcti;
- a->flow_id = ai.flows[fd].info.id;
+ a->flow_id = proc.flows[fd].info.id;
pthread_mutex_lock(&rw.lock);
diff --git a/src/lib/utils.c b/src/lib/utils.c
index 74f8ce4f..cfddec62 100644
--- a/src/lib/utils.c
+++ b/src/lib/utils.c
@@ -20,11 +20,15 @@
* Foundation, Inc., http://www.fsf.org/about/contact/.
*/
-#define _POSIX_C_SOURCE 200809L
+#define _DEFAULT_SOURCE
+
+#include "config.h"
#include <ouroboros/utils.h>
#include <ctype.h>
+#include <grp.h>
+#include <pwd.h>
#include <stdlib.h>
#include <string.h>
@@ -138,5 +142,63 @@ char ** argvdup(char ** argv)
}
argv_dup[argc] = NULL;
+
return argv_dup;
}
+
+bool is_ouroboros_member_uid(uid_t uid)
+{
+ struct group * grp;
+ struct passwd * pw;
+ gid_t gid;
+ gid_t * groups = NULL;
+ int ngroups;
+ int i;
+
+ /* Root is always privileged */
+ if (uid == 0)
+ return true;
+
+ grp = getgrnam("ouroboros");
+ if (grp == NULL)
+ return false;
+
+ gid = grp->gr_gid;
+
+ pw = getpwuid(uid);
+ if (pw == NULL)
+ return false;
+
+ if (pw->pw_gid == gid)
+ return true;
+
+ ngroups = 0;
+ getgrouplist(pw->pw_name, pw->pw_gid, NULL, &ngroups);
+ if (ngroups <= 0)
+ return false;
+
+ groups = malloc(ngroups * sizeof(*groups));
+ if (groups == NULL)
+ return false;
+
+ if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups) < 0) {
+ free(groups);
+ return false;
+ }
+
+ for (i = 0; i < ngroups; i++) {
+ if (groups[i] == gid) {
+ free(groups);
+ return true;
+ }
+ }
+
+ free(groups);
+
+ return false;
+}
+
+bool is_ouroboros_member(void)
+{
+ return is_ouroboros_member_uid(getuid());
+}
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
new file mode 100644
index 00000000..3cec8172
--- /dev/null
+++ b/src/tools/CMakeLists.txt
@@ -0,0 +1,71 @@
+# Tools build configuration
+
+set(TOOLS_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_BINARY_DIR}/include
+)
+
+set(IRM_SOURCES
+ irm/irm.c
+ irm/irm_bind_program.c
+ irm/irm_bind_process.c
+ irm/irm_bind_ipcp.c
+ irm/irm_ipcp_create.c
+ irm/irm_ipcp_destroy.c
+ irm/irm_ipcp_bootstrap.c
+ irm/irm_ipcp_enroll.c
+ irm/irm_ipcp_list.c
+ irm/irm_ipcp_connect.c
+ irm/irm_ipcp_disconnect.c
+ irm/irm_unbind_program.c
+ irm/irm_unbind_process.c
+ irm/irm_unbind_ipcp.c
+ irm/irm_unbind.c
+ irm/irm_bind.c
+ irm/irm_ipcp.c
+ irm/irm_name.c
+ irm/irm_name_create.c
+ irm/irm_name_destroy.c
+ irm/irm_name_reg.c
+ irm/irm_name_unreg.c
+ irm/irm_name_list.c
+ irm/irm_utils.c
+)
+
+add_executable(irm ${IRM_SOURCES})
+target_include_directories(irm PRIVATE ${TOOLS_INCLUDE_DIRS})
+target_link_libraries(irm PRIVATE ouroboros-irm)
+install(TARGETS irm RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
+
+add_executable(oping oping/oping.c)
+target_include_directories(oping PRIVATE ${TOOLS_INCLUDE_DIRS})
+target_link_libraries(oping PRIVATE ${LIBM_LIBRARIES} ouroboros-dev)
+install(TARGETS oping RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+add_executable(oecho oecho/oecho.c)
+target_include_directories(oecho PRIVATE ${TOOLS_INCLUDE_DIRS})
+target_link_libraries(oecho PRIVATE ouroboros-dev)
+install(TARGETS oecho RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+add_executable(ocbr ocbr/ocbr.c)
+target_include_directories(ocbr PRIVATE ${TOOLS_INCLUDE_DIRS})
+target_link_libraries(ocbr PRIVATE ouroboros-dev)
+install(TARGETS ocbr RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+add_executable(obc obc/obc.c)
+target_include_directories(obc PRIVATE ${TOOLS_INCLUDE_DIRS})
+target_link_libraries(obc PRIVATE ouroboros-dev)
+install(TARGETS obc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+add_executable(operf operf/operf.c)
+target_include_directories(operf PRIVATE ${TOOLS_INCLUDE_DIRS})
+target_link_libraries(operf PRIVATE ouroboros-dev)
+install(TARGETS operf RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ add_executable(ovpn ovpn/ovpn.c)
+ target_include_directories(ovpn PRIVATE ${TOOLS_INCLUDE_DIRS})
+ target_link_libraries(ovpn PRIVATE ouroboros-dev)
+ install(TARGETS ovpn RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+endif()
diff --git a/src/tools/oping/oping.c b/src/tools/oping/oping.c
index 87c1ee18..47b86c68 100644
--- a/src/tools/oping/oping.c
+++ b/src/tools/oping/oping.c
@@ -75,12 +75,14 @@
"\n" \
" -c, --count Number of packets\n" \
" -d, --duration Duration of the test (default 1s)\n" \
+" -f, --flood Send back-to-back without waiting\n" \
" -i, --interval Interval (default 1000ms)\n" \
" -n, --server-name Name of the oping server\n" \
" -q, --qos QoS (raw, best, video, voice, data)\n" \
" -s, --size Payload size (B, default 64)\n" \
" -Q, --quiet Only print final statistics\n" \
" -D, --timeofday Print time of day before each line\n" \
+" --poll Server uses polling (lower latency)\n" \
"\n" \
" --help Display this help text and exit\n" \
@@ -90,6 +92,7 @@ struct {
uint32_t count;
int size;
bool timestamp;
+ bool flood;
qosspec_t qs;
/* stats */
@@ -114,6 +117,7 @@ struct {
pthread_mutex_t lock;
bool quiet;
+ bool poll;
pthread_t cleaner_pt;
pthread_t accept_pt;
@@ -172,9 +176,11 @@ int main(int argc,
client.size = 64;
client.count = INT_MAX;
client.timestamp = false;
+ client.flood = false;
client.qs = qos_raw;
client.quiet = false;
server.quiet = false;
+ server.poll = false;
while (argc > 0) {
if ((strcmp(*argv, "-i") == 0 ||
@@ -212,6 +218,9 @@ int main(int argc,
} else if (strcmp(*argv, "-l") == 0 ||
strcmp(*argv, "--listen") == 0) {
serv = true;
+ } else if (strcmp(*argv, "-f") == 0 ||
+ strcmp(*argv, "--flood") == 0) {
+ client.flood = true;
} else if (strcmp(*argv, "-D") == 0 ||
strcmp(*argv, "--timeofday") == 0) {
client.timestamp = true;
@@ -219,6 +228,8 @@ int main(int argc,
strcmp(*argv, "--quiet") == 0) {
client.quiet = true;
server.quiet = true;
+ } else if (strcmp(*argv, "--poll") == 0) {
+ server.poll = true;
} else {
goto fail;
}
diff --git a/src/tools/oping/oping_client.c b/src/tools/oping/oping_client.c
index 5a9e03dc..1513eac8 100644
--- a/src/tools/oping/oping_client.c
+++ b/src/tools/oping/oping_client.c
@@ -53,6 +53,20 @@ void shutdown_client(int signo, siginfo_t * info, void * c)
}
}
+static void update_rtt_stats(double ms)
+{
+ double d;
+
+ if (ms < client.rtt_min)
+ client.rtt_min = ms;
+ if (ms > client.rtt_max)
+ client.rtt_max = ms;
+
+ d = (ms - client.rtt_avg);
+ client.rtt_avg += d / client.rcvd;
+ client.rtt_m2 += d * (ms - client.rtt_avg);
+}
+
void * reader(void * o)
{
struct timespec timeout = {client.interval / 1000 + 2, 0};
@@ -64,7 +78,6 @@ void * reader(void * o)
int fd = *((int *) o);
int msg_len = 0;
double ms = 0;
- double d = 0;
uint32_t exp_id = 0;
fccntl(fd, FLOWSRCVTIMEO, &timeout);
@@ -122,14 +135,7 @@ void * reader(void * o)
id < exp_id ? " [out-of-order]" : "");
}
- if (ms < client.rtt_min)
- client.rtt_min = ms;
- if (ms > client.rtt_max)
- client.rtt_max = ms;
-
- d = (ms - client.rtt_avg);
- client.rtt_avg += d / client.rcvd;
- client.rtt_m2 += d * (ms - client.rtt_avg);
+ update_rtt_stats(ms);
if (id >= exp_id)
exp_id = id + 1;
@@ -204,13 +210,103 @@ static void client_fini(void)
return;
}
+static void print_stats(struct timespec * tic,
+ struct timespec * toc)
+{
+ printf("\n");
+ printf("--- %s ping statistics ---\n", client.s_apn);
+ printf("%d packets transmitted, ", client.sent);
+ printf("%d received, ", client.rcvd);
+ printf("%zd out-of-order, ", client.ooo);
+ printf("%.0lf%% packet loss, ", client.sent == 0 ? 0 :
+ ceil(100 - (100 * (client.rcvd / (float) client.sent))));
+ printf("time: %.3f ms\n", ts_diff_us(toc, tic) / 1000.0);
+
+ if (client.rcvd > 0) {
+ printf("rtt min/avg/max/mdev = %.3f/%.3f/%.3f/",
+ client.rtt_min,
+ client.rtt_avg,
+ client.rtt_max);
+ if (client.rcvd > 1)
+ printf("%.3f ms\n",
+ sqrt(client.rtt_m2 / (client.rcvd - 1)));
+ else
+ printf("NaN ms\n");
+ }
+}
+
+static int flood_ping(int fd)
+{
+ char buf[OPING_BUF_SIZE];
+ struct oping_msg * msg = (struct oping_msg *) buf;
+ struct timespec sent;
+ struct timespec rcvd;
+ double ms;
+
+ memset(buf, 0, client.size);
+
+ if (!client.quiet)
+ printf("Pinging %s with %d bytes of data (%u packets):\n\n",
+ client.s_apn, client.size, client.count);
+
+ while (!stop && client.sent < client.count) {
+ clock_gettime(CLOCK_MONOTONIC, &sent);
+
+ msg->type = htonl(ECHO_REQUEST);
+ msg->id = htonl(client.sent);
+ msg->tv_sec = sent.tv_sec;
+ msg->tv_nsec = sent.tv_nsec;
+
+ if (flow_write(fd, buf, client.size) < 0) {
+ printf("Failed to send packet.\n");
+ break;
+ }
+
+ ++client.sent;
+
+ if (flow_read(fd, buf, OPING_BUF_SIZE) < 0) {
+ printf("Failed to read packet.\n");
+ break;
+ }
+
+ clock_gettime(CLOCK_MONOTONIC, &rcvd);
+
+ if (ntohl(msg->type) != ECHO_REPLY)
+ continue;
+
+ ++client.rcvd;
+
+ sent.tv_sec = msg->tv_sec;
+ sent.tv_nsec = msg->tv_nsec;
+ ms = ts_diff_us(&rcvd, &sent) / 1000.0;
+
+ update_rtt_stats(ms);
+
+ if (!client.quiet)
+ printf("%d bytes from %s: seq=%d time=%.3f ms\n",
+ client.size, client.s_apn,
+ ntohl(msg->id), ms);
+ }
+
+ return 0;
+}
+
+static int threaded_ping(int fd)
+{
+ pthread_create(&client.reader_pt, NULL, reader, &fd);
+ pthread_create(&client.writer_pt, NULL, writer, &fd);
+
+ pthread_join(client.writer_pt, NULL);
+ pthread_join(client.reader_pt, NULL);
+
+ return 0;
+}
+
static int client_main(void)
{
struct sigaction sig_act;
-
struct timespec tic;
struct timespec toc;
-
int fd;
memset(&sig_act, 0, sizeof sig_act);
@@ -241,37 +337,16 @@ static int client_main(void)
clock_gettime(CLOCK_REALTIME, &tic);
- pthread_create(&client.reader_pt, NULL, reader, &fd);
- pthread_create(&client.writer_pt, NULL, writer, &fd);
-
- pthread_join(client.writer_pt, NULL);
- pthread_join(client.reader_pt, NULL);
+ if (client.flood)
+ flood_ping(fd);
+ else
+ threaded_ping(fd);
clock_gettime(CLOCK_REALTIME, &toc);
- printf("\n");
- printf("--- %s ping statistics ---\n", client.s_apn);
- printf("%d packets transmitted, ", client.sent);
- printf("%d received, ", client.rcvd);
- printf("%zd out-of-order, ", client.ooo);
- printf("%.0lf%% packet loss, ", client.sent == 0 ? 0 :
- ceil(100 - (100 * (client.rcvd / (float) client.sent))));
- printf("time: %.3f ms\n", ts_diff_us(&toc, &tic) / 1000.0);
-
- if (client.rcvd > 0) {
- printf("rtt min/avg/max/mdev = %.3f/%.3f/%.3f/",
- client.rtt_min,
- client.rtt_avg,
- client.rtt_max);
- if (client.rcvd > 1)
- printf("%.3f ms\n",
- sqrt(client.rtt_m2 / (client.rcvd - 1)));
- else
- printf("NaN ms\n");
- }
+ print_stats(&tic, &toc);
flow_dealloc(fd);
-
client_fini();
return 0;
diff --git a/src/tools/oping/oping_server.c b/src/tools/oping/oping_server.c
index c1d5e6e5..13ab8f47 100644
--- a/src/tools/oping/oping_server.c
+++ b/src/tools/oping/oping_server.c
@@ -89,12 +89,15 @@ void * server_thread(void *o)
struct oping_msg * msg = (struct oping_msg *) buf;
struct timespec now = {0, 0};
struct timespec timeout = {0, 100 * MILLION};
+ struct timespec poll_timeout = {0, 0};
int fd;
(void) o;
while (true) {
- if (fevent(server.flows, server.fq, &timeout) == -ETIMEDOUT)
+ if (fevent(server.flows, server.fq,
+ server.poll ? &poll_timeout : &timeout)
+ == -ETIMEDOUT)
continue;
while ((fd = fqueue_next(server.fq)) >= 0) {