diff --git a/.gitignore b/.gitignore index 12d23e2..67de247 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ __pycache__/ .pytest_cache/ mock-bpa-test/ccsds_bpsec_redbook_requirements_modified.yaml +/deps/ diff --git a/src/BPSecLib_Private.h b/src/BPSecLib_Private.h index ff62529..b0f97db 100644 --- a/src/BPSecLib_Private.h +++ b/src/BPSecLib_Private.h @@ -173,37 +173,6 @@ typedef enum */ char *BSL_Log_DumpAsHexString(char *dstbuf, size_t dstlen, const uint8_t *srcbuf, size_t srclen); -/** Opens the event log. - * @note This should be called once per process, not thread or library instance. - * At the end of the process there should be a call to BSL_closelog() - * - * This is a mimic to POSIX @c openlog() - */ -void BSL_openlog(void); - -/** Closes the event log. - * This is a mimic to POSIX @c closelog() - * @sa BSL_openlog - */ -void BSL_closelog(void); - -/** Interpret a text name as a severity level. - * - * @param[out] severity The associated severity level. - * @param[in] name The text name, which is case insensitive. - * @return Zero if successful. - */ -int BSL_LogGetSeverity(int *severity, const char *name); - -/** Set the least severity enabled for logging. - * Other events will be dropped by the logging facility. - * This function is multi-thread safe. - * - * @param severity The severity from a subset of the POSIX syslog values. - * @sa BSL_log_is_enabled_for() - */ -void BSL_LogSetLeastSeverity(int severity); - /** Determine if a particular severity is being logged. * This function is multi-thread safe. * @@ -343,9 +312,8 @@ int BSL_SeqWriter_Put(BSL_SeqWriter_t *obj, const uint8_t *buf, size_t bufsize); /** Initialize an abstract EID. * * @param[out] eid The object to initialize. - * @return Zero if successful. */ -int BSL_HostEID_Init(BSL_HostEID_t *eid); +void BSL_HostEID_Init(BSL_HostEID_t *eid); /** De-initialize an abstract EID. * diff --git a/src/BPSecLib_Public.h b/src/BPSecLib_Public.h index 698141f..bdf12da 100644 --- a/src/BPSecLib_Public.h +++ b/src/BPSecLib_Public.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include "BSLConfig.h" #include "Data.h" @@ -297,6 +299,9 @@ typedef struct } /** Dynamic BPA descriptor. + * + * @caution All functions in this structure must be thread safe, as they + * can be called by any number of BSL instances across any threads. */ typedef struct { @@ -307,7 +312,7 @@ typedef struct int (*get_sec_src_eid_fn)(void *user_data, BSL_HostEID_t *result); /// @brief Host BPA function to initialize/allocate an EID type. - int (*eid_init)(void *user_data, BSL_HostEID_t *result); + void (*eid_init)(void *user_data, BSL_HostEID_t *result); /// @brief Host BPA function to deinit/free an EID type. void (*eid_deinit)(void *user_data, BSL_HostEID_t *eid); @@ -387,9 +392,36 @@ typedef struct /// @brief Host BPA function that returns true if the given EID matched an EID pattern. bool (*eidpat_match)(const BSL_HostEIDPattern_t *pat, const BSL_HostEID_t *eid, void *user_data); + /** Called to check if logging is enabled for at least a specific severity. + * + * @note If not provided by the host, this defaults to always-true. + * + * @param severity The severity from a subset of the POSIX syslog values. + * @return True if logging will occur for that severity level. + */ + bool (*log_is_enabled_for)(int severity); + + /** Called for each log event from the BSL and its PP and SC instances. + * All input text strings must be copied by the callback if they are + * referenced outside of that callback. + * + * @note If not provided by the host, this defaults to writing + * synchronously to @c stderr. + * + * @param timestamp The timestamp of the original event. + * @param severity The severity from a subset of the POSIX syslog values. + * This value has already been filtered by #log_is_enabled_for. + * @param[in] filename The originating file name, which may include directory parts. + * @param[in] lineno The originating file line number. + * @param[in] funcname The originating function name. + * @param[in] format The log message format string. + * @param args Values for the format string. + */ + void (*log_event)(const struct timeval *timestamp, int severity, const char *filename, int lineno, + const char *funcname, const char *format, va_list args); + /// @brief Optionally set dynamic memory management callbacks. Defaults to libc calls if unset. BSL_DynMemHostDescriptors_t dyn_mem_desc; - } BSL_HostDescriptors_t; /** Set the BPA descriptor (callbacks) for this process. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c3297af..4580c80 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -126,7 +126,6 @@ set(BSL_DYNAMIC_C ${CMAKE_CURRENT_SOURCE_DIR}/backend/AbsSecBlock.c ${CMAKE_CURRENT_SOURCE_DIR}/backend/HostInterface.c ${CMAKE_CURRENT_SOURCE_DIR}/backend/PublicInterfaceImpl.c - ${CMAKE_CURRENT_SOURCE_DIR}/backend/LoggingStderr.c ${CMAKE_CURRENT_SOURCE_DIR}/backend/PolicyProvider.c ${CMAKE_CURRENT_SOURCE_DIR}/backend/TelemetryCounters.c ${CMAKE_CURRENT_SOURCE_DIR}/backend/SecOperation.c diff --git a/src/backend/HostInterface.c b/src/backend/HostInterface.c index aceb5d3..b55306f 100644 --- a/src/backend/HostInterface.c +++ b/src/backend/HostInterface.c @@ -23,6 +23,9 @@ * @brief Implementation of the host BPA and its callback functions. * @ingroup backend_dyn */ +#include +#include +#include #include #include "UtilDefs_SeqReadWrite.h" @@ -162,11 +165,11 @@ void BSL_HostDescriptors_Clear(void) HostDescriptorTable = (BSL_HostDescriptors_t) { 0 }; } -int BSL_HostEID_Init(BSL_HostEID_t *eid) +void BSL_HostEID_Init(BSL_HostEID_t *eid) { - CHK_ARG_NONNULL(eid); - CHK_PRECONDITION(HostDescriptorTable.eid_init != NULL); - return HostDescriptorTable.eid_init(HostDescriptorTable.user_data, eid); + ASSERT_ARG_NONNULL(eid); + ASSERT_PRECONDITION(HostDescriptorTable.eid_init != NULL); + HostDescriptorTable.eid_init(HostDescriptorTable.user_data, eid); } void BSL_HostEID_Deinit(BSL_HostEID_t *eid) @@ -239,6 +242,110 @@ bool BSL_HostEIDPattern_IsMatch(const BSL_HostEIDPattern_t *pat, const BSL_HostE return HostDescriptorTable.eidpat_match(pat, eid, HostDescriptorTable.user_data); } +// NOLINTBEGIN +static const char *log_sev_names[] = { + NULL, // LOG_EMERG + NULL, // LOG_ALERT + "CRIT", // LOG_CRIT + "ERROR", // LOG_ERR + "WARNING", // LOG_WARNING + NULL, // LOG_NOTICE + "INFO", // LOG_INFO + "DEBUG", // LOG_DEBUG +}; +// NOLINTEND + +bool BSL_LogIsEnabledFor(int severity) +{ + if ((severity < 0) || (severity >= 7)) + { + // not valid + return false; + } + + if (!HostDescriptorTable.log_is_enabled_for) + { + return true; + } + + return HostDescriptorTable.log_is_enabled_for(severity); +} + +void BSL_LogEvent(int severity, const char *filename, int lineno, const char *funcname, const char *format, ...) +{ + if (!BSL_LogIsEnabledFor(severity)) + { + return; + } + + struct timeval timestamp; + gettimeofday(×tamp, NULL); + + va_list args; + va_start(args, format); + + if (!HostDescriptorTable.log_event) + { + char tmbuf[32]; // NOLINT + { + time_t nowtime = timestamp.tv_sec; + struct tm nowtm; + gmtime_r(&nowtime, &nowtm); + + char *curs = tmbuf; + size_t remain = sizeof(tmbuf) - 1; + size_t len = strftime(curs, remain, "%Y-%m-%dT%H:%M:%S", &nowtm); + curs += len; + remain -= len; + snprintf(curs, remain, ".%06ld", timestamp.tv_usec); + } + + const char *severity_name = log_sev_names[severity]; + + pthread_t thread = pthread_self(); + char thrbuf[2 * sizeof(pthread_t) + 1]; + size_t remain = sizeof(thrbuf); + { + const uint8_t *data = (const void *)&thread; + char *out = thrbuf; + for (size_t ix = 0; ix < sizeof(pthread_t); ++ix) + { + snprintf(out, remain, "%02X", *data); + data++; + out += 2; + remain -= 2; + } + *out = '\0'; + } + + // simplify filename + static const char dirsep = '/'; + const char *filepos = strrchr(filename, dirsep); + if (filepos) + { + filepos += 1; + } + else + { + filepos = filename; + } + + fprintf(stderr, "%s T:%s <%s> [%s:%d:%s] ", tmbuf, thrbuf, severity_name, filepos, lineno, funcname); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + vfprintf(stderr, format, args); +#pragma GCC diagnostic pop + fprintf(stderr, "\n"); + fflush(stderr); + } + else + { + HostDescriptorTable.log_event(×tamp, severity, filename, lineno, funcname, format, args); + } + + va_end(args); +} + void *BSL_malloc(size_t size) { return HostDescriptorTable.dyn_mem_desc.malloc_cb(size); diff --git a/src/backend/PublicInterfaceImpl.c b/src/backend/PublicInterfaceImpl.c index 3588eb5..a220fe6 100644 --- a/src/backend/PublicInterfaceImpl.c +++ b/src/backend/PublicInterfaceImpl.c @@ -34,6 +34,23 @@ #include "SecurityActionSet.h" #include "SecurityResultSet.h" +char *BSL_Log_DumpAsHexString(char *dstbuf, size_t dstlen, const uint8_t *srcbuf, size_t srclen) +{ + ASSERT_ARG_NONNULL(dstbuf); + ASSERT_ARG_NONNULL(srcbuf); + ASSERT_ARG_EXPR(dstlen > 0); + ASSERT_ARG_EXPR(srclen > 0); + + memset(dstbuf, 0, dstlen); + const char hex_digits[] = "0123456789ABCDEF"; + for (size_t i = 0; i < srclen && (((i * 2) + 1) < dstlen - 1); i++) + { + dstbuf[(i * 2)] = hex_digits[(srcbuf[i] >> 4) & 0x0F]; + dstbuf[(i * 2) + 1] = hex_digits[srcbuf[i] & 0x0F]; + } + return dstbuf; +} + size_t BSL_LibCtx_Sizeof(void) { return sizeof(BSL_LibCtx_t); diff --git a/src/mock_bpa/CMakeLists.txt b/src/mock_bpa/CMakeLists.txt index 010d2f6..7869050 100644 --- a/src/mock_bpa/CMakeLists.txt +++ b/src/mock_bpa/CMakeLists.txt @@ -25,6 +25,7 @@ target_compile_options(bsl_mock_bpa PRIVATE -Wshadow -Wpointer-arith -Wstrict-pr target_sources( bsl_mock_bpa PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/log.h ${CMAKE_CURRENT_SOURCE_DIR}/agent.h ${CMAKE_CURRENT_SOURCE_DIR}/bundle.h ${CMAKE_CURRENT_SOURCE_DIR}/crc.h @@ -41,6 +42,7 @@ target_sources( ) target_sources( bsl_mock_bpa PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/log.c ${CMAKE_CURRENT_SOURCE_DIR}/agent.c ${CMAKE_CURRENT_SOURCE_DIR}/bundle.c ${CMAKE_CURRENT_SOURCE_DIR}/crc.c diff --git a/src/mock_bpa/MockBPA.h b/src/mock_bpa/MockBPA.h index cc02a9a..da16c53 100644 --- a/src/mock_bpa/MockBPA.h +++ b/src/mock_bpa/MockBPA.h @@ -26,6 +26,7 @@ #include "encode.h" #include "decode.h" #include "eidpat.h" +#include "log.h" #include "agent.h" #endif //_BSL_MockBPA_MockBPA_H_ diff --git a/src/mock_bpa/agent.c b/src/mock_bpa/agent.c index 4ff3c2c..0a8bb44 100644 --- a/src/mock_bpa/agent.c +++ b/src/mock_bpa/agent.c @@ -33,6 +33,7 @@ #include #include #include "agent.h" +#include "log.h" #include "eid.h" #include "eidpat.h" #include "encode.h" @@ -406,6 +407,9 @@ BSL_HostDescriptors_t MockBPA_Agent_Descriptors(MockBPA_Agent_t *agent) .eidpat_deinit = mock_bpa_eidpat_deinit, .eidpat_from_text = mock_bpa_eidpat_from_text, .eidpat_match = mock_bpa_eidpat_match, + + .log_is_enabled_for = mock_bpa_LogIsEnabledFor, + .log_event = mock_bpa_LogEvent, }; return bpa; } diff --git a/src/mock_bpa/eid.c b/src/mock_bpa/eid.c index 2f75172..73ebcc0 100644 --- a/src/mock_bpa/eid.c +++ b/src/mock_bpa/eid.c @@ -53,17 +53,15 @@ void bsl_mock_eid_deinit(bsl_mock_eid_t *eid) memset(eid, 0, sizeof(bsl_mock_eid_t)); } -int MockBPA_EID_Init(void *user_data _U_, BSL_HostEID_t *eid) +void MockBPA_EID_Init(void *user_data _U_, BSL_HostEID_t *eid) { - BSL_CHKERR1(eid); + BSL_CHKVOID(eid); memset(eid, 0, sizeof(BSL_HostEID_t)); eid->handle = BSL_malloc(sizeof(bsl_mock_eid_t)); - if (!(eid->handle)) + if (eid->handle) { - return -2; + bsl_mock_eid_init(eid->handle); } - bsl_mock_eid_init(eid->handle); - return 0; } void MockBPA_EID_Deinit(void *user_data _U_, BSL_HostEID_t *eid) diff --git a/src/mock_bpa/eid.h b/src/mock_bpa/eid.h index c76aa3e..7f34984 100644 --- a/src/mock_bpa/eid.h +++ b/src/mock_bpa/eid.h @@ -78,7 +78,7 @@ void bsl_mock_eid_init(bsl_mock_eid_t *eid); void bsl_mock_eid_deinit(bsl_mock_eid_t *eid); /// Interface for BSL_HostDescriptors_t::eid_init -int MockBPA_EID_Init(void *user_data, BSL_HostEID_t *eid); +void MockBPA_EID_Init(void *user_data, BSL_HostEID_t *eid); /// Interface for BSL_HostDescriptors_t::eid_deinit void MockBPA_EID_Deinit(void *user_data, BSL_HostEID_t *eid); diff --git a/src/backend/LoggingStderr.c b/src/mock_bpa/log.c similarity index 60% rename from src/backend/LoggingStderr.c rename to src/mock_bpa/log.c index a603031..c06b36b 100644 --- a/src/backend/LoggingStderr.c +++ b/src/mock_bpa/log.c @@ -20,25 +20,29 @@ * subcontract 1700763. */ /** @file - * Implementation of event logging using @c stderr output stream. - * @ingroup backend_dyn + * @ingroup mock_bpa + * Logging implementation for the Mock BPA. + * This uses the @c stderr output stream in a work thread to ensure thread + * safety of event sources. */ +#include "log.h" +#include +#include + #include #include #include #include +#include #include #include -#include -#include - #include #include #include /// Number of events to buffer to I/O thread -#define BSL_LOG_QUEUE_SIZE 100 +#define MOCK_BPA_LOG_QUEUE_SIZE 100 // NOLINTBEGIN static const char *sev_names[] = { @@ -66,24 +70,24 @@ typedef struct string_t context; /// Fully formatted message string_t message; -} BSL_LogEvent_event_t; +} mock_bpa_LogEvent_event_t; -static void BSL_LogEvent_event_init(BSL_LogEvent_event_t *obj) +static void mock_bpa_LogEvent_event_init(mock_bpa_LogEvent_event_t *obj) { - obj->thread = pthread_self(); - gettimeofday(&(obj->timestamp), NULL); - obj->severity = LOG_DEBUG; + obj->thread = pthread_self(); + obj->timestamp = (struct timeval) { 0 }; + obj->severity = LOG_DEBUG; string_init(obj->context); string_init(obj->message); } -static void BSL_LogEvent_event_deinit(BSL_LogEvent_event_t *obj) +static void mock_bpa_LogEvent_event_deinit(mock_bpa_LogEvent_event_t *obj) { string_clear(obj->message); string_clear(obj->context); } -static void BSL_LogEvent_event_init_set(BSL_LogEvent_event_t *obj, const BSL_LogEvent_event_t *src) +static void mock_bpa_LogEvent_event_init_set(mock_bpa_LogEvent_event_t *obj, const mock_bpa_LogEvent_event_t *src) { obj->thread = src->thread; obj->timestamp = src->timestamp; @@ -92,7 +96,7 @@ static void BSL_LogEvent_event_init_set(BSL_LogEvent_event_t *obj, const BSL_Log string_init_set(obj->message, src->message); } -static void BSL_LogEvent_event_init_move(BSL_LogEvent_event_t *obj, BSL_LogEvent_event_t *src) +static void mock_bpa_LogEvent_event_init_move(mock_bpa_LogEvent_event_t *obj, mock_bpa_LogEvent_event_t *src) { obj->thread = src->thread; obj->timestamp = src->timestamp; @@ -101,7 +105,7 @@ static void BSL_LogEvent_event_init_move(BSL_LogEvent_event_t *obj, BSL_LogEvent string_init_move(obj->message, src->message); } -static void BSL_LogEvent_event_set(BSL_LogEvent_event_t *obj, const BSL_LogEvent_event_t *src) +static void mock_bpa_LogEvent_event_set(mock_bpa_LogEvent_event_t *obj, const mock_bpa_LogEvent_event_t *src) { obj->thread = src->thread; obj->timestamp = src->timestamp; @@ -110,16 +114,16 @@ static void BSL_LogEvent_event_set(BSL_LogEvent_event_t *obj, const BSL_LogEvent string_set(obj->message, src->message); } -/// OPLIST for BSL_LogEvent_event_t -#define M_OPL_BSL_LogEvent_event_t() \ - (INIT(API_2(BSL_LogEvent_event_init)), INIT_SET(API_6(BSL_LogEvent_event_init_set)), \ - INIT_MOVE(API_6(BSL_LogEvent_event_init_move)), SET(API_6(BSL_LogEvent_event_set)), \ - CLEAR(API_2(BSL_LogEvent_event_deinit))) +/// OPLIST for mock_bpa_LogEvent_event_t +#define M_OPL_mock_bpa_LogEvent_event_t() \ + (INIT(API_2(mock_bpa_LogEvent_event_init)), INIT_SET(API_6(mock_bpa_LogEvent_event_init_set)), \ + INIT_MOVE(API_6(mock_bpa_LogEvent_event_init_move)), SET(API_6(mock_bpa_LogEvent_event_set)), \ + CLEAR(API_2(mock_bpa_LogEvent_event_deinit))) // NOLINTBEGIN /// @cond Doxygen_Suppress // GCOV_EXCL_START -M_BUFFER_DEF(BSL_LogEvent_queue, BSL_LogEvent_event_t, BSL_LOG_QUEUE_SIZE, +M_BUFFER_DEF(mock_bpa_LogEvent_queue, mock_bpa_LogEvent_event_t, MOCK_BPA_LOG_QUEUE_SIZE, M_BUFFER_THREAD_SAFE | M_BUFFER_BLOCKING | M_BUFFER_PUSH_INIT_POP_MOVE) // GCOV_EXCL_STOP /// @endcond @@ -128,37 +132,20 @@ M_BUFFER_DEF(BSL_LogEvent_queue, BSL_LogEvent_event_t, BSL_LOG_QUEUE_SIZE, static atomic_int least_severity = LOG_DEBUG; /// Shared safe queue -static BSL_LogEvent_queue_t event_queue; +static mock_bpa_LogEvent_queue_t event_queue; /// Sink thread ID static pthread_t thr_sink; /// True if ::thr_sink is valid static atomic_bool thr_valid = ATOMIC_VAR_INIT(false); // NOLINTEND -char *BSL_Log_DumpAsHexString(char *dstbuf, size_t dstlen, const uint8_t *srcbuf, size_t srclen) -{ - ASSERT_ARG_NONNULL(dstbuf); - ASSERT_ARG_NONNULL(srcbuf); - ASSERT_ARG_EXPR(dstlen > 0); - ASSERT_ARG_EXPR(srclen > 0); - - memset(dstbuf, 0, dstlen); - const char hex_digits[] = "0123456789ABCDEF"; - for (size_t i = 0; i < srclen && (((i * 2) + 1) < dstlen - 1); i++) - { - dstbuf[(i * 2)] = hex_digits[(srcbuf[i] >> 4) & 0x0F]; - dstbuf[(i * 2) + 1] = hex_digits[srcbuf[i] & 0x0F]; - } - return dstbuf; -} - // NOLINTBEGIN -static void write_log(const BSL_LogEvent_event_t *event) +static void write_log(const mock_bpa_LogEvent_event_t *event) { ASSERT_ARG_NONNULL(event); // already domain validated - const char *prioname = sev_names[event->severity]; + const char *severity_name = sev_names[event->severity]; char tmbuf[32]; // NOLINT { @@ -175,17 +162,19 @@ static void write_log(const BSL_LogEvent_event_t *event) } char thrbuf[2 * sizeof(pthread_t) + 1]; { - const uint8_t *data = (const void *)&(event->thread); - char *out = thrbuf; + const uint8_t *data = (const void *)&(event->thread); + char *out = thrbuf; + size_t remain = sizeof(thrbuf); for (size_t ix = 0; ix < sizeof(pthread_t); ++ix) { - sprintf(out, "%02X", *data); + snprintf(out, remain, "%02X", *data); data++; out += 2; + remain -= 2; } *out = '\0'; } - fprintf(stderr, "%s T:%s <%s> [%s] %s\n", tmbuf, thrbuf, prioname, string_get_cstr(event->context), + fprintf(stderr, "%s T:%s <%s> [%s] %s\n", tmbuf, thrbuf, severity_name, string_get_cstr(event->context), string_get_cstr(event->message)); fflush(stderr); } @@ -196,8 +185,8 @@ static void *work_sink(void *arg _U_) bool running = true; while (running) { - BSL_LogEvent_event_t event; - BSL_LogEvent_queue_pop(&event, event_queue); + mock_bpa_LogEvent_event_t event; + mock_bpa_LogEvent_queue_pop(&event, event_queue); if (string_empty_p(event.message)) { running = false; @@ -206,24 +195,24 @@ static void *work_sink(void *arg _U_) { write_log(&event); } - BSL_LogEvent_event_deinit(&event); + mock_bpa_LogEvent_event_deinit(&event); } return NULL; } -void BSL_openlog(void) +void mock_bpa_LogOpen(void) { - BSL_LogEvent_queue_init(event_queue, BSL_LOG_QUEUE_SIZE); + mock_bpa_LogEvent_queue_init(event_queue, MOCK_BPA_LOG_QUEUE_SIZE); if (pthread_create(&thr_sink, NULL, work_sink, NULL)) { // unsynchronized write - BSL_LogEvent_event_t manual; - BSL_LogEvent_event_init(&manual); + mock_bpa_LogEvent_event_t manual; + mock_bpa_LogEvent_event_init(&manual); manual.severity = LOG_CRIT; - string_set_str(manual.message, "BSL_openlog() failed"); + string_set_str(manual.message, "mock_bpa_LogOpen() failed"); write_log(&manual); - BSL_LogEvent_event_deinit(&manual); + mock_bpa_LogEvent_event_deinit(&manual); } else { @@ -231,24 +220,24 @@ void BSL_openlog(void) } } -void BSL_closelog(void) +void mock_bpa_LogClose(void) { // sentinel empty message - BSL_LogEvent_event_t event; - BSL_LogEvent_event_init(&event); - BSL_LogEvent_queue_push(event_queue, event); - BSL_LogEvent_event_deinit(&event); + mock_bpa_LogEvent_event_t event; + mock_bpa_LogEvent_event_init(&event); + mock_bpa_LogEvent_queue_push(event_queue, event); + mock_bpa_LogEvent_event_deinit(&event); int res = pthread_join(thr_sink, NULL); if (res) { // unsynchronized write - BSL_LogEvent_event_t manual; - BSL_LogEvent_event_init(&manual); + mock_bpa_LogEvent_event_t manual; + mock_bpa_LogEvent_event_init(&manual); manual.severity = LOG_CRIT; - string_set_str(manual.message, "BSL_closelog() failed"); + string_set_str(manual.message, "mock_bpa_LogClose() failed"); write_log(&manual); - BSL_LogEvent_event_deinit(&manual); + mock_bpa_LogEvent_event_deinit(&manual); } else { @@ -256,10 +245,10 @@ void BSL_closelog(void) } // no consumer after join above - BSL_LogEvent_queue_clear(event_queue); + mock_bpa_LogEvent_queue_clear(event_queue); } -int BSL_LogGetSeverity(int *severity, const char *name) +int mock_bpa_LogGetSeverity(int *severity, const char *name) { BSL_CHKERR1(severity); BSL_CHKERR1(name); @@ -279,7 +268,7 @@ int BSL_LogGetSeverity(int *severity, const char *name) return 2; } -void BSL_LogSetLeastSeverity(int severity) +void mock_bpa_LogSetLeastSeverity(int severity) { if ((severity < 0) || (severity > LOG_DEBUG)) { @@ -289,13 +278,8 @@ void BSL_LogSetLeastSeverity(int severity) atomic_store(&least_severity, severity); } -bool BSL_LogIsEnabledFor(int severity) +bool mock_bpa_LogIsEnabledFor(int severity) { - if ((severity < 0) || (severity > LOG_DEBUG)) - { - return false; - } - const int limit = atomic_load(&least_severity); // lower severity has higher define value const bool enabled = (limit >= severity); @@ -304,16 +288,15 @@ bool BSL_LogIsEnabledFor(int severity) } // NOLINTBEGIN -void BSL_LogEvent(int severity, const char *filename, int lineno, const char *funcname, const char *format, ...) +void mock_bpa_LogEvent(const struct timeval *timestamp, int severity, const char *filename, int lineno, + const char *funcname, const char *format, va_list args) { - if (!BSL_LogIsEnabledFor(severity)) - { - return; - } + BSL_CHKVOID(timestamp); - BSL_LogEvent_event_t event; - BSL_LogEvent_event_init(&event); - event.severity = severity; + mock_bpa_LogEvent_event_t event; + mock_bpa_LogEvent_event_init(&event); + event.timestamp = *timestamp; + event.severity = severity; if (filename) { @@ -331,32 +314,27 @@ void BSL_LogEvent(int severity, const char *filename, int lineno, const char *fu string_printf(event.context, "%s:%d:%s", pos, lineno, funcname); } - { - va_list val; - va_start(val, format); - string_vprintf(event.message, format, val); - va_end(val); - } + string_vprintf(event.message, format, args); // ignore empty messages if (!string_empty_p(event.message)) { if (atomic_load(&thr_valid)) { - BSL_LogEvent_queue_push(event_queue, event); + mock_bpa_LogEvent_queue_push(event_queue, event); } else { - BSL_LogEvent_event_t manual; - BSL_LogEvent_event_init(&manual); + mock_bpa_LogEvent_event_t manual; + mock_bpa_LogEvent_event_init(&manual); manual.severity = LOG_CRIT; - string_set_str(manual.message, "BSL_LogEvent() called before BSL_openlog()"); + string_set_str(manual.message, "mock_bpa_LogEvent() called before mock_bpa_openlog()"); write_log(&manual); - BSL_LogEvent_event_deinit(&manual); + mock_bpa_LogEvent_event_deinit(&manual); write_log(&event); } } - BSL_LogEvent_event_deinit(&event); + mock_bpa_LogEvent_event_deinit(&event); } // NOLINTEND diff --git a/src/mock_bpa/log.h b/src/mock_bpa/log.h new file mode 100644 index 0000000..e60de30 --- /dev/null +++ b/src/mock_bpa/log.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025-2026 The Johns Hopkins University Applied Physics + * Laboratory LLC. + * + * This file is part of the Bundle Protocol Security Library (BSL). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This work was performed for the Jet Propulsion Laboratory, California + * Institute of Technology, sponsored by the United States Government under + * the prime contract 80NM0018D0004 between the Caltech and NASA under + * subcontract 1700763. + */ +/** @file + * @ingroup mock_bpa + * Logging interface for the Mock BPA. + */ + +#ifndef BSL_MOCK_BPA_LOG_H_ +#define BSL_MOCK_BPA_LOG_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Opens the event log. + * @note This should be called once per process, not thread or library instance. + * At the end of the process there should be a call to mock_bpa_LogClose(). + * + * This is a mimic to POSIX @c openlog() + */ +void mock_bpa_LogOpen(void); + +/** Closes the event log. + * This is a mimic to POSIX @c closelog() + */ +void mock_bpa_LogClose(void); + +/** Interpret a text name as a severity level. + * + * @param[out] severity The associated severity level. + * @param[in] name The text name, which is case insensitive. + * @return Zero if successful. + */ +int mock_bpa_LogGetSeverity(int *severity, const char *name); + +/** Set the least severity enabled for logging. + * Other events will be dropped by the logging facility. + * This function is multi-thread safe. + * + * @param severity The severity from a subset of the POSIX syslog values. + */ +void mock_bpa_LogSetLeastSeverity(int severity); + +/// Interface for BSL_HostDescriptors_t::log_is_enabled_for +bool mock_bpa_LogIsEnabledFor(int severity); +/// Interface for BSL_HostDescriptors_t::log_event +void mock_bpa_LogEvent(const struct timeval *timestamp, int severity, const char *filename, int lineno, + const char *funcname, const char *format, va_list args); + +#ifdef __cplusplus +} // extern C +#endif + +#endif /* BSL_MOCK_BPA_LOG_H_ */ diff --git a/src/mock_bpa/mock_bpa.c b/src/mock_bpa/mock_bpa.c index 0a8aa5e..b9b5eb8 100644 --- a/src/mock_bpa/mock_bpa.c +++ b/src/mock_bpa/mock_bpa.c @@ -36,6 +36,7 @@ #include #include "agent.h" +#include "log.h" #include "policy_config.h" // Configuration @@ -104,21 +105,21 @@ static void show_usage(const char *argv0) int main(int argc, char **argv) { + int retval = 0; + int res; + if (BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(&agent))) { return 2; } - - BSL_openlog(); - int retval = 0; - int res; - + mock_bpa_LogOpen(); BSL_CryptoInit(); if ((res = MockBPA_Agent_Init(&agent))) { BSL_LOG_ERR("Failed to initialize mock BPA, error %d", res); retval = 2; } + if (!retval) { struct sigaction stopper = { .sa_handler = sig_stop, @@ -126,7 +127,7 @@ int main(int argc, char **argv) sigaction(SIGINT, &stopper, NULL); sigaction(SIGTERM, &stopper, NULL); } - + // always run these steps BSL_HostEID_Init(&app_eid); BSL_HostEID_Init(&sec_eid); @@ -254,7 +255,7 @@ int main(int argc, char **argv) BSL_HostEID_Deinit(&app_eid); BSL_CryptoDeinit(); - BSL_closelog(); + mock_bpa_LogClose(); BSL_HostDescriptors_Clear(); return retval; } diff --git a/test/fuzz_dynamic_asb_cbor.cpp b/test/fuzz_dynamic_asb_cbor.cpp index 9a42379..b51e937 100644 --- a/test/fuzz_dynamic_asb_cbor.cpp +++ b/test/fuzz_dynamic_asb_cbor.cpp @@ -35,8 +35,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); extern "C" int LLVMFuzzerInitialize(int *argc _U_, char ***argv _U_) { BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL)); - BSL_openlog(); - BSL_LogSetLeastSeverity(LOG_CRIT); + mock_bpa_LogOpen(); + mock_bpa_LogSetLeastSeverity(LOG_CRIT); return 0; } diff --git a/test/fuzz_mock_bpa_bpv7_cbor.cpp b/test/fuzz_mock_bpa_bpv7_cbor.cpp index 0074f44..2dda448 100644 --- a/test/fuzz_mock_bpa_bpv7_cbor.cpp +++ b/test/fuzz_mock_bpa_bpv7_cbor.cpp @@ -35,8 +35,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); extern "C" int LLVMFuzzerInitialize(int *argc _U_, char ***argv _U_) { BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL)); - BSL_openlog(); - BSL_LogSetLeastSeverity(LOG_CRIT); + mock_bpa_LogOpen(); + mock_bpa_LogSetLeastSeverity(LOG_CRIT); return 0; } diff --git a/test/fuzz_mock_bpa_eid_cbor.cpp b/test/fuzz_mock_bpa_eid_cbor.cpp index d3ec526..cfc5fd6 100644 --- a/test/fuzz_mock_bpa_eid_cbor.cpp +++ b/test/fuzz_mock_bpa_eid_cbor.cpp @@ -35,8 +35,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); extern "C" int LLVMFuzzerInitialize(int *argc _U_, char ***argv _U_) { BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL)); - BSL_openlog(); - BSL_LogSetLeastSeverity(LOG_CRIT); + mock_bpa_LogOpen(); + mock_bpa_LogSetLeastSeverity(LOG_CRIT); return 0; } diff --git a/test/fuzz_mock_bpa_eid_uri.cpp b/test/fuzz_mock_bpa_eid_uri.cpp index 2a2a9d0..ba9171c 100644 --- a/test/fuzz_mock_bpa_eid_uri.cpp +++ b/test/fuzz_mock_bpa_eid_uri.cpp @@ -37,8 +37,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); extern "C" int LLVMFuzzerInitialize(int *argc _U_, char ***argv _U_) { BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL)); - BSL_openlog(); - BSL_LogSetLeastSeverity(LOG_CRIT); + mock_bpa_LogOpen(); + mock_bpa_LogSetLeastSeverity(LOG_CRIT); return 0; } diff --git a/test/fuzz_mock_bpa_eidpat_text.cpp b/test/fuzz_mock_bpa_eidpat_text.cpp index 5668807..2a9f350 100644 --- a/test/fuzz_mock_bpa_eidpat_text.cpp +++ b/test/fuzz_mock_bpa_eidpat_text.cpp @@ -37,8 +37,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); extern "C" int LLVMFuzzerInitialize(int *argc _U_, char ***argv _U_) { BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL)); - BSL_openlog(); - BSL_LogSetLeastSeverity(LOG_CRIT); + mock_bpa_LogOpen(); + mock_bpa_LogSetLeastSeverity(LOG_CRIT); return 0; } diff --git a/test/test_AbsSecBlock.c b/test/test_AbsSecBlock.c index 72e9506..dc9ce2b 100644 --- a/test/test_AbsSecBlock.c +++ b/test/test_AbsSecBlock.c @@ -37,12 +37,13 @@ void suiteSetUp(void) { TEST_ASSERT_EQUAL_INT(0, BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL))); - BSL_openlog(); + mock_bpa_LogOpen(); + mock_bpa_LogSetLeastSeverity(LOG_CRIT); } int suiteTearDown(int failures) { - BSL_closelog(); + mock_bpa_LogClose(); BSL_HostDescriptors_Clear(); return failures; } diff --git a/test/test_BackendPolicyProvider.c b/test/test_BackendPolicyProvider.c index f01d478..c860e63 100644 --- a/test/test_BackendPolicyProvider.c +++ b/test/test_BackendPolicyProvider.c @@ -45,12 +45,12 @@ static BSL_TestContext_t LocalTestCtx; void suiteSetUp(void) { TEST_ASSERT_EQUAL_INT(0, BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL))); - BSL_openlog(); + mock_bpa_LogOpen(); } int suiteTearDown(int failures) { - BSL_closelog(); + mock_bpa_LogClose(); BSL_HostDescriptors_Clear(); return failures; } diff --git a/test/test_BackendSecurityContext.c b/test/test_BackendSecurityContext.c index 40cbbd3..b9ce858 100644 --- a/test/test_BackendSecurityContext.c +++ b/test/test_BackendSecurityContext.c @@ -47,12 +47,12 @@ static BSL_TestContext_t LocalTestCtx; void suiteSetUp(void) { TEST_ASSERT_EQUAL_INT(0, BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL))); - BSL_openlog(); + mock_bpa_LogOpen(); } int suiteTearDown(int failures) { - BSL_closelog(); + mock_bpa_LogClose(); BSL_HostDescriptors_Clear(); return failures; } diff --git a/test/test_CryptoInterface.c b/test/test_CryptoInterface.c index bbc7048..aadea8c 100644 --- a/test/test_CryptoInterface.c +++ b/test/test_CryptoInterface.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "bsl_test_utils.h" @@ -199,12 +200,13 @@ static uint8_t test_256[32] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, void suiteSetUp(void) { TEST_ASSERT_EQUAL_INT(0, BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL))); - BSL_openlog(); + mock_bpa_LogOpen(); + mock_bpa_LogSetLeastSeverity(LOG_CRIT); } int suiteTearDown(int failures) { - BSL_closelog(); + mock_bpa_LogClose(); return failures; } diff --git a/test/test_DefaultSecurityContext.c b/test/test_DefaultSecurityContext.c index 4107c29..3f07137 100644 --- a/test/test_DefaultSecurityContext.c +++ b/test/test_DefaultSecurityContext.c @@ -52,12 +52,13 @@ static BSL_TestContext_t LocalTestCtx; void suiteSetUp(void) { TEST_ASSERT_EQUAL_INT(0, BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL))); - BSL_openlog(); + mock_bpa_LogOpen(); + mock_bpa_LogSetLeastSeverity(LOG_CRIT); } int suiteTearDown(int failures) { - BSL_closelog(); + mock_bpa_LogClose(); BSL_HostDescriptors_Clear(); return failures; } diff --git a/test/test_DynamicMemCbs.c b/test/test_DynamicMemCbs.c index 75f26b3..59a4138 100644 --- a/test/test_DynamicMemCbs.c +++ b/test/test_DynamicMemCbs.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "bsl_test_utils.h" @@ -79,12 +80,12 @@ void suiteSetUp(void) host_desc.dyn_mem_desc = dyn_mem_desc; TEST_ASSERT_EQUAL_INT(0, BSL_HostDescriptors_Set(host_desc)); - BSL_openlog(); + mock_bpa_LogOpen(); } int suiteTearDown(int failures) { - BSL_closelog(); + mock_bpa_LogClose(); BSL_HostDescriptors_Clear(); return failures; } diff --git a/test/test_MockBPA_Codecs.c b/test/test_MockBPA_Codecs.c index 7c0f821..ba54406 100644 --- a/test/test_MockBPA_Codecs.c +++ b/test/test_MockBPA_Codecs.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -51,12 +52,12 @@ static void printencoded(const uint8_t *pEncoded, size_t nLen) void suiteSetUp(void) { TEST_ASSERT_EQUAL_INT(0, BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL))); - BSL_openlog(); + mock_bpa_LogOpen(); } int suiteTearDown(int failures) { - BSL_closelog(); + mock_bpa_LogClose(); BSL_HostDescriptors_Clear(); return failures; } diff --git a/test/test_MockBPA_EID.c b/test/test_MockBPA_EID.c index b9c58d0..6f2a83b 100644 --- a/test/test_MockBPA_EID.c +++ b/test/test_MockBPA_EID.c @@ -24,18 +24,19 @@ #include #include #include +#include #define TEST_CASE(...) void suiteSetUp(void) { TEST_ASSERT_EQUAL_INT(0, BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL))); - BSL_openlog(); + mock_bpa_LogOpen(); } int suiteTearDown(int failures) { - BSL_closelog(); + mock_bpa_LogClose(); BSL_HostDescriptors_Clear(); return failures; } @@ -85,7 +86,7 @@ TEST_CASE("ipn:4294967296.0") // authority present void test_BSL_HostEID_DecodeFromText_valid(const char *text) { BSL_HostEID_t eid; - TEST_ASSERT_EQUAL_INT(0, BSL_HostEID_Init(&eid)); + BSL_HostEID_Init(&eid); int res = BSL_HostEID_DecodeFromText(&eid, text); TEST_ASSERT_EQUAL_INT_MESSAGE(0, res, "BSL_HostEID_DecodeFromText() failed"); diff --git a/test/test_PublicInterfaceImpl.c b/test/test_PublicInterfaceImpl.c index cf0c3b5..a6c85df 100644 --- a/test/test_PublicInterfaceImpl.c +++ b/test/test_PublicInterfaceImpl.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "bsl_test_utils.h" @@ -60,12 +61,12 @@ static BSL_TestPublInterfaceCtx_t ctx = { 0 }; void suiteSetUp(void) { TEST_ASSERT_EQUAL_INT(0, BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL))); - BSL_openlog(); + mock_bpa_LogOpen(); } int suiteTearDown(int failures) { - BSL_closelog(); + mock_bpa_LogClose(); BSL_HostDescriptors_Clear(); return failures; } diff --git a/test/test_SamplePolicyProvider.c b/test/test_SamplePolicyProvider.c index b37c97e..db603cc 100644 --- a/test/test_SamplePolicyProvider.c +++ b/test/test_SamplePolicyProvider.c @@ -41,12 +41,12 @@ static BSL_TestContext_t LocalTestCtx; void suiteSetUp(void) { TEST_ASSERT_EQUAL_INT(0, BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL))); - BSL_openlog(); + mock_bpa_LogOpen(); } int suiteTearDown(int failures) { - BSL_closelog(); + mock_bpa_LogClose(); BSL_HostDescriptors_Clear(); return failures; } diff --git a/test/test_mock_bpa_ctr.c b/test/test_mock_bpa_ctr.c index 53f3519..4249140 100644 --- a/test/test_mock_bpa_ctr.c +++ b/test/test_mock_bpa_ctr.c @@ -24,16 +24,17 @@ #include "bsl_test_utils.h" #include #include +#include void suiteSetUp(void) { TEST_ASSERT_EQUAL_INT(0, BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL))); - BSL_openlog(); + mock_bpa_LogOpen(); } int suiteTearDown(int failures) { - BSL_closelog(); + mock_bpa_LogClose(); BSL_HostDescriptors_Clear(); return failures; }