diff --git a/.github/workflows/native-build.yml b/.github/workflows/native-build.yml index b8c6054..f1d0bc0 100644 --- a/.github/workflows/native-build.yml +++ b/.github/workflows/native-build.yml @@ -32,5 +32,3 @@ jobs: # Build component chmod +x build_tools_workflows/cov_docker_script/build_native.sh ./build_tools_workflows/cov_docker_script/build_native.sh ./cov_docker_script/component_config.json "$(pwd)" - env: - GITHUB_TOKEN: ${{ secrets.RDKCM_RDKE }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ed3985..69bfcac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,11 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). -#### 2.8.1 +#### 2.9.0 +- RDKB-67262: Remove Github token from Native build [`#112`](https://github.com/rdkcentral/advanced-security/pull/112) +- RDKB-66812 RDKB-66844 : Pause Network Intelligence while speedtest is running [`#103`](https://github.com/rdkcentral/advanced-security/pull/103) +- RDKB-66811 RDKB-66952 : Support webconfig schema for opt-in / opt-out of Network Intelligence feature [`#109`](https://github.com/rdkcentral/advanced-security/pull/109) - RDKB-66811 RDKB-66952 : Support end user opt-in / opt-out for Network Intelligence feature [`#107`](https://github.com/rdkcentral/advanced-security/pull/107) - RDKB-66906 : Stop Network Intelligence service in start_adv_security.sh disable logic [`#108`](https://github.com/rdkcentral/advanced-security/pull/108) - RDKB-66906 : Make cujo-ni service restart dependent on cujo-agent restart [`#104`](https://github.com/rdkcentral/advanced-security/pull/104) @@ -48,5 +51,5 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Create fossid_integration_stateless_diffscan_target_repo.yml [`#2`](https://github.com/rdkcentral/advanced-security/pull/2) - Create CODEOWNERS file [`#1`](https://github.com/rdkcentral/advanced-security/pull/1) - Import of source (stable2) [`55740fb`](https://github.com/rdkcentral/advanced-security/commit/55740fbcd9f7f71a3b57d286f6f9b6f919819b8b) +- Add changelog for release 2.8.1 [`198b1d0`](https://github.com/rdkcentral/advanced-security/commit/198b1d0be656ce552639f3581abb278910a65991) - updating the changelog.md file [`c155519`](https://github.com/rdkcentral/advanced-security/commit/c1555192bbe6c2e48ac278a70b3e2a3137cd5a38) -- Add changelog for release 2.8.0 [`243972f`](https://github.com/rdkcentral/advanced-security/commit/243972f5e443e88e447b5fbd6fe8cd45b49457b0) diff --git a/config/TR181-AdvSecurity.xml b/config/TR181-AdvSecurity.xml index 0f8a3cd..f946b63 100644 --- a/config/TR181-AdvSecurity.xml +++ b/config/TR181-AdvSecurity.xml @@ -75,6 +75,7 @@ NetworkIntelligence_GetParamBoolValue NetworkIntelligence_SetParamBoolValue + NetworkIntelligence_SetParamStringValue @@ -83,6 +84,12 @@ bool true + + Data + string + string + true + diff --git a/source/AdvSecurityDml/Makefile.am b/source/AdvSecurityDml/Makefile.am index 22d45a9..da1e1c3 100644 --- a/source/AdvSecurityDml/Makefile.am +++ b/source/AdvSecurityDml/Makefile.am @@ -26,7 +26,7 @@ hardware_platform = i686-linux-gnu lib_LTLIBRARIES = libdmlasecurity.la libdmlasecurity_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/source/AdvSecurityDml -I$(top_srcdir)/source/AdvSecuritySsp $(CPPFLAGS) -I$(top_srcdir)/../Utopia/source/include/sysevent -I${PKG_CONFIG_SYSROOT_DIR}$(includedir)/rbus libdmlasecurity_la_SOURCES = plugin_main.c cosa_adv_security_internal.c cosa_adv_security_dml.c cosa_adv_security_webconfig.c advsecurity_helpers.c advsecurity_param.c -libdmlasecurity_la_LDFLAGS = -lccsp_common -lsyscfg -lsysevent -lwebconfig_framework -lmsgpackc -ltrower-base64 -lsecure_wrapper -lrbus -lev -lpthread $(SSP_LDFLAGS) +libdmlasecurity_la_LDFLAGS = -lccsp_common -lsyscfg -lsysevent -lwebconfig_framework -lmsgpackc -ltrower-base64 -lsecure_wrapper -lrbus -lev -lpthread -ltelemetry_msgsender $(SSP_LDFLAGS) if WIFI_DATA_COLLECTION libdmlasecurity_la_CPPFLAGS += -DDML_SUPPORT -DWIFI_DATA_COLLECTION @@ -36,5 +36,6 @@ endif if NETWORK_INTELLIGENCE libdmlasecurity_la_CPPFLAGS += -DDML_SUPPORT -DNETWORK_INTELLIGENCE +libdmlasecurity_la_SOURCES += cosa_network_intelligence_webconfig.c networkintelligence_param.c libdmlasecurity_la_LDFLAGS += -lwifi_webconfig endif \ No newline at end of file diff --git a/source/AdvSecurityDml/advsecurity_param.c b/source/AdvSecurityDml/advsecurity_param.c index b110899..c8b7bd6 100644 --- a/source/AdvSecurityDml/advsecurity_param.c +++ b/source/AdvSecurityDml/advsecurity_param.c @@ -114,15 +114,10 @@ const char* advsecuritydoc_strerror( int errnum ) int process_advsecurityparams( advsecurityparam_t *e, msgpack_object_map *map ) { int left = map->size; - /* Bits 0-4 are the mandatory legacy parameters. NetworkIntelligenceActivate - * is optional for backward compatibility with the older 5-parameter schema; - * when absent it retains its zeroed default. */ uint8_t objects_left = 0x1F; msgpack_object_kv *p; p = map->ptr; - /* Iterate every entry: optional parameters may follow the last mandatory - * one, so we must not stop early once objects_left reaches zero. */ - while( 0 < left-- ) + while( (0 < left--) && (0 != objects_left) ) { if( MSGPACK_OBJECT_STR == p->key.type ) { @@ -153,12 +148,6 @@ int process_advsecurityparams( advsecurityparam_t *e, msgpack_object_map *map ) e->privacy_protection_activate = p->val.via.boolean; objects_left &= ~(1 << 4); } - if( 0 == match(p, "NetworkIntelligenceActivate") ) - { - e->network_intelligence_activate = p->val.via.boolean; - e->network_intelligence_present = true; - objects_left &= ~(1 << 5); - } } } p++; diff --git a/source/AdvSecurityDml/advsecurity_param.h b/source/AdvSecurityDml/advsecurity_param.h index ff7b016..9489d3a 100644 --- a/source/AdvSecurityDml/advsecurity_param.h +++ b/source/AdvSecurityDml/advsecurity_param.h @@ -31,11 +31,6 @@ typedef struct bool safebrowsing_enable; bool parental_control_activate; bool privacy_protection_activate; - bool network_intelligence_activate; - /* False when the payload used the older 5-parameter schema that omits - * NetworkIntelligenceActivate. In that case network_intelligence_activate - * carries no meaning and must not be applied. */ - bool network_intelligence_present; } advsecurityparam_t; diff --git a/source/AdvSecurityDml/cosa_adv_security_dml.c b/source/AdvSecurityDml/cosa_adv_security_dml.c index e8c01ad..1ffc3ab 100644 --- a/source/AdvSecurityDml/cosa_adv_security_dml.c +++ b/source/AdvSecurityDml/cosa_adv_security_dml.c @@ -21,6 +21,10 @@ #include "ansc_platform.h" #include "cosa_adv_security_internal.h" #include "cosa_adv_security_webconfig.h" +#ifdef NETWORK_INTELLIGENCE +#include "cosa_network_intelligence_webconfig.h" +#include "networkintelligence_param.h" +#endif #include "syslog.h" #include "ccsp_trace.h" #include "msgpack.h" @@ -573,7 +577,7 @@ AdvancedSecurity_SetParamStringValue errno_t rc = -1; int ind = -1; - if(ParamName == NULL) + if((ParamName == NULL) || (pString == NULL)) return FALSE; /* check the parameter name and set the corresponding value */ rc = strcmp_s("Data", strlen("Data"), ParamName, &ind); @@ -592,10 +596,30 @@ AdvancedSecurity_SetParamStringValue msgpack_unpack_return unpack_ret; decodeMsgSize = b64_get_decoded_buffer_size(strlen(pString)); + if(decodeMsgSize <= 0) + { + CcspTraceError(("Invalid base64 decoded buffer size %d\n", decodeMsgSize)); + return FALSE; + } + decodeMsg = (char *) AnscAllocateMemory(sizeof(char) * decodeMsgSize); + if(decodeMsg == NULL) + { + CcspTraceError(("decodeMsg AnscAllocateMemory failed\n")); + return FALSE; + } + size = b64_decode((uint8_t *) pString, strlen(pString),(uint8_t *) decodeMsg ); CcspTraceInfo(("base64 decoded data contains %d bytes\n",size)); + if((size <= 0) || (size > decodeMsgSize)) + { + CcspTraceError(("base64 decode failed, invalid length %d (buffer %d)\n", size, decodeMsgSize)); + AnscFreeMemory(decodeMsg); + decodeMsg = NULL; + return FALSE; + } + msgpack_zone_init(&mempool, 2048); unpack_ret = msgpack_unpack(decodeMsg, size, NULL, &mempool, &deserialized); switch(unpack_ret) @@ -629,23 +653,14 @@ AdvancedSecurity_SetParamStringValue err = errno; CcspTraceInfo(("errno: %s\n", advsecuritydoc_strerror(err))); - if(ad != NULL) + if(ad != NULL && ad->param != NULL && ad->subdoc_name != NULL) { CcspTraceInfo(("ad->subdoc_name is %s\n", ad->subdoc_name)); CcspTraceInfo(("ad->version is %lu\n", (long)ad->version)); CcspTraceInfo(("ad->transaction_id %lu\n",(long) ad->transaction_id)); - if (ad->param->network_intelligence_present) - { - CcspTraceInfo(("fingerprint_enable:[%d], softflowd_enable[%d], safebrowsing_enable[%d], parental_control_activate[%d], privacy_protection_activate[%d], network_intelligence_activate[%d]\n", - ad->param->fingerprint_enable,ad->param->softflowd_enable,ad->param->safebrowsing_enable, - ad->param->parental_control_activate,ad->param->privacy_protection_activate,ad->param->network_intelligence_activate)); - } - else - { - CcspTraceInfo(("fingerprint_enable:[%d], softflowd_enable[%d], safebrowsing_enable[%d], parental_control_activate[%d], privacy_protection_activate[%d]\n", - ad->param->fingerprint_enable,ad->param->softflowd_enable,ad->param->safebrowsing_enable, - ad->param->parental_control_activate,ad->param->privacy_protection_activate)); - } + CcspTraceInfo(("fingerprint_enable:[%d], softflowd_enable[%d], safebrowsing_enable[%d], parental_control_activate[%d], privacy_protection_activate[%d]\n", + ad->param->fingerprint_enable,ad->param->softflowd_enable,ad->param->safebrowsing_enable, + ad->param->parental_control_activate,ad->param->privacy_protection_activate)); execData *execDataAdvsec = NULL ; execDataAdvsec = (execData*) AnscAllocateMemory (sizeof(execData)); @@ -691,6 +706,17 @@ AdvancedSecurity_SetParamStringValue ret_val = FALSE; } } + else if(ad != NULL) + { + CcspTraceError(("advsecuritydoc missing mandatory fields\n")); + advsecuritydoc_destroy(ad); + ret_val = FALSE; + } + else + { + CcspTraceError(("advsecuritydoc_convert failed\n")); + ret_val = FALSE; + } } else { @@ -4214,6 +4240,196 @@ NetworkIntelligence_RFC_SetParamUlongValue CcspTraceWarning(("Unsupported parameter '%s'\n", ParamName)); return FALSE; } + +/********************************************************************** + + caller: owner of this object + + prototype: + + BOOL + NetworkIntelligence_SetParamStringValue + ( + ANSC_HANDLE hInsContext, + char* ParamName, + char* pString + ); + + description: + + This function is called to set string parameter value; + + argument: ANSC_HANDLE hInsContext, + The instance handle; + + char* ParamName, + The parameter name; + + char* pString + The updated string value; + + return: TRUE if succeeded. + +**********************************************************************/ +BOOL +NetworkIntelligence_SetParamStringValue + ( + ANSC_HANDLE hInsContext, + char* ParamName, + char* pString + ) +{ + UNREFERENCED_PARAMETER(hInsContext); + errno_t rc = -1; + int ind = -1; + + if(ParamName == NULL || pString == NULL) + return FALSE; + + /* check the parameter name and set the corresponding value */ + rc = strcmp_s("Data", strlen("Data"), ParamName, &ind); + ERR_CHK(rc); + if((rc == EOK) && (!ind)) + { + networkintelligencedoc_t *nd = NULL; + int err; + char * decodeMsg = NULL; + int decodeMsgSize = 0; + int size = 0; + BOOL ret_val = TRUE; + + msgpack_zone mempool; + msgpack_object deserialized; + msgpack_unpack_return unpack_ret; + + decodeMsgSize = b64_get_decoded_buffer_size(strlen(pString)); + if (decodeMsgSize <= 0) + { + CcspTraceError(("Invalid base64 decoded buffer size %d\n", decodeMsgSize)); + return FALSE; + } + + decodeMsg = (char *) AnscAllocateMemory(sizeof(char) * decodeMsgSize); + if (decodeMsg == NULL) + { + CcspTraceError(("decodeMsg AnscAllocateMemory failed\n")); + return FALSE; + } + size = b64_decode((uint8_t *) pString, strlen(pString),(uint8_t *) decodeMsg ); + CcspTraceInfo(("base64 decoded data contains %d bytes\n",size)); + + if ((size <= 0) || (size > decodeMsgSize)) + { + CcspTraceError(("base64 decode failed, invalid length %d (buffer %d)\n", size, decodeMsgSize)); + AnscFreeMemory(decodeMsg); + decodeMsg = NULL; + return FALSE; + } + + msgpack_zone_init(&mempool, 2048); + unpack_ret = msgpack_unpack(decodeMsg, size, NULL, &mempool, &deserialized); + switch(unpack_ret) + { + case MSGPACK_UNPACK_SUCCESS: + CcspTraceInfo(("MSGPACK_UNPACK_SUCCESS :%d\n",unpack_ret)); + break; + case MSGPACK_UNPACK_EXTRA_BYTES: + CcspTraceInfo(("MSGPACK_UNPACK_EXTRA_BYTES :%d\n",unpack_ret)); + break; + case MSGPACK_UNPACK_CONTINUE: + CcspTraceInfo(("MSGPACK_UNPACK_CONTINUE :%d\n",unpack_ret)); + break; + case MSGPACK_UNPACK_PARSE_ERROR: + CcspTraceError(("MSGPACK_UNPACK_PARSE_ERROR :%d\n",unpack_ret)); + break; + case MSGPACK_UNPACK_NOMEM_ERROR: + CcspTraceError(("MSGPACK_UNPACK_NOMEM_ERROR :%d\n",unpack_ret)); + break; + default: + CcspTraceError(("Message Pack decode failed with error: %d\n", unpack_ret)); + } + msgpack_zone_destroy(&mempool); + + CcspTraceInfo(("---------------End of b64 decode--------------\n")); + + if(unpack_ret == MSGPACK_UNPACK_SUCCESS) + { + CcspTraceInfo(("Msg unpack success\n")); + nd = networkintelligencedoc_convert(decodeMsg, size);//used to process the incoming msgobject + err = errno; + CcspTraceInfo(("errno: %s\n", networkintelligencedoc_strerror(err))); + + if(nd != NULL && nd->param != NULL && nd->subdoc_name != NULL) + { + CcspTraceInfo(("nd->subdoc_name is %s\n", nd->subdoc_name)); + CcspTraceInfo(("nd->version is %lu\n", (long)nd->version)); + CcspTraceInfo(("nd->transaction_id %lu\n",(long) nd->transaction_id)); + CcspTraceInfo(("network_intelligence_activate:[%d]\n", + nd->param->network_intelligence_activate)); + + execData *execDataNi = NULL ; + execDataNi = (execData*) AnscAllocateMemory (sizeof(execData)); + + if ( execDataNi != NULL ) + { + rc = memset_s(execDataNi, sizeof(execData), 0, sizeof(execData)); + ERR_CHK(rc); + + execDataNi->txid = nd->transaction_id; + execDataNi->version = nd->version; + execDataNi->numOfEntries = 1; + + rc = strcpy_s(execDataNi->subdoc_name, sizeof(execDataNi->subdoc_name), nd->subdoc_name); + if(rc != EOK) + { + ERR_CHK(rc); + AnscFreeMemory(execDataNi); + execDataNi = NULL; + networkintelligencedoc_destroy(nd); + AnscFreeMemory(decodeMsg); + decodeMsg = NULL; + return FALSE; + } + + execDataNi->user_data = (void*) nd; + execDataNi->calcTimeout = NULL ; + execDataNi->executeBlobRequest = ni_webconfig_process_request; + execDataNi->rollbackFunc = ni_webconfig_rollback; + execDataNi->freeResources = ni_webconfig_free_resources; + PushBlobRequest(execDataNi); + CcspTraceInfo(("PushBlobRequest complete\n")); + } + else + { + CcspTraceError(("execData AnscAllocateMemory failed\n")); + networkintelligencedoc_destroy(nd); + ret_val = FALSE; + } + } + else + { + CcspTraceError(("Failed to convert networkintelligence subdoc\n")); + networkintelligencedoc_destroy(nd); + ret_val = FALSE; + } + } + else + { + CcspTraceError(("Failed to unpack msgpack\n")); + ret_val = FALSE; + } + + if ( decodeMsg ) + { + AnscFreeMemory (decodeMsg); + decodeMsg = NULL; + } + return ret_val; + } + + CcspTraceWarning(("Unsupported parameter '%s'\n", ParamName)); + return FALSE; +} #endif // NETWORK_INTELLIGENCE /*********************************************************************** diff --git a/source/AdvSecurityDml/cosa_adv_security_dml.h b/source/AdvSecurityDml/cosa_adv_security_dml.h index 94b878a..3196f39 100644 --- a/source/AdvSecurityDml/cosa_adv_security_dml.h +++ b/source/AdvSecurityDml/cosa_adv_security_dml.h @@ -631,6 +631,23 @@ NetworkIntelligence_RFC_SetParamUlongValue char* ParamName, ULONG uValue ); + +/*********************************************************************** + + APIs for Object: + + X_RDKCENTRAL-COM_NetworkIntelligence. + + * NetworkIntelligence_SetParamStringValue + +***********************************************************************/ +BOOL +NetworkIntelligence_SetParamStringValue + ( + ANSC_HANDLE hInsContext, + char* ParamName, + char* pString + ); #endif // NETWORK_INTELLIGENCE /*********************************************************************** diff --git a/source/AdvSecurityDml/cosa_adv_security_internal.c b/source/AdvSecurityDml/cosa_adv_security_internal.c index 389adbb..0564b00 100644 --- a/source/AdvSecurityDml/cosa_adv_security_internal.c +++ b/source/AdvSecurityDml/cosa_adv_security_internal.c @@ -33,6 +33,9 @@ #include "cosa_adv_security_internal.h" #include "cosa_adv_security_dml.h" #include "cosa_adv_security_webconfig.h" +#ifdef NETWORK_INTELLIGENCE +#include "cosa_network_intelligence_webconfig.h" +#endif #include "ccsp_psm_helper.h" #include #include @@ -66,6 +69,10 @@ #define ADVSEC_SYSEVENT_CURRENT_WAN_IFNAME_EVENT "current_wan_ifname" #define LEVL_DML "Device.WiFi.Levl" +#define SPEEDTEST_STATUS_DML "Device.IP.Diagnostics.X_RDKCENTRAL-COM_SpeedTest.Status" +#define SPEEDTEST_TIMEOUT_DML "Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut" +#define ADVSEC_NETWORKINTELLIGENCE_ENABLED_PATH "/tmp/advsec_networkintelligence_enabled" +#define CUJONICLI_SET_QOSD_ENABLE_CMD "/usr/bin/cujo-ni-cli '{\"method\":\"set_configs\", \"configs\": {\"cujoniqos.daemon.enable\": %d}}' &" #define ADVSEC_WAIT_FOR_TIMEOUT (60 * 60) #define MAX_VALUE 32 @@ -152,6 +159,11 @@ static char *g_RaptrEnabled = "Adv_RaptrRFCEnable"; #ifdef NETWORK_INTELLIGENCE static char *g_AdvSecNetworkIntelligenceEnabled = "Adv_AdvSecNetworkIntelligenceRFCEnable"; static char *g_NetworkIntelligenceMemoryLimit = "Advsecurity_NetworkIntelligenceMemoryLimit"; +STATIC pthread_mutex_t ni_speedtest_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t ni_speedtest_cond = PTHREAD_COND_INITIALIZER; +static struct timespec ni_speedtest_timeout; +STATIC BOOL ni_speedtest_thread_running = FALSE; +static BOOL ni_speedtest_wake_early = FALSE; static char *g_NetworkIntelligenceActivate = "Adv_AdvSecNetworkIntelligenceActivate"; #endif #ifdef WIFI_DATA_COLLECTION @@ -431,6 +443,215 @@ static void eventReceiveHandler( } #endif +#ifdef NETWORK_INTELLIGENCE +static BOOL is_ni_enabled_and_activated(void) +{ + struct stat st; + + if (stat(ADVSEC_NETWORKINTELLIGENCE_ENABLED_PATH, &st) != 0) + { + return FALSE; + } + if (stat(ADVSEC_NETWORKINTELLIGENCE_ACTIVATED_PATH, &st) != 0) + { + return FALSE; + } + return TRUE; +} + +static BOOL ni_qosd_enable(BOOL enable) +{ + errno_t rc; + + rc = v_secure_system(CUJONICLI_SET_QOSD_ENABLE_CMD, enable ? 1 : 0); + if (!WIFEXITED(rc) || WEXITSTATUS(rc) != 0) + { + CcspTraceError(("%s: cujo-ni-cli set_configs cujoniqos.daemon.enable=%d failed, rc=%d\n", + __FUNCTION__, enable ? 1 : 0, WEXITSTATUS(rc))); + return FALSE; + } + if (enable) + { + t2_event_d("SYS_INFO_CUJO_NI_resume", 1); + } + else + { + t2_event_d("SYS_INFO_CUJO_NI_pause", 1); + } + return TRUE; +} + +static void *ni_speedtest_handler(void *arg) +{ + int waitStatus = 0; + BOOL timedOut; + + (void)arg; + + pthread_detach(pthread_self()); + + pthread_mutex_lock(&ni_speedtest_mutex); + if (!ni_qosd_enable(FALSE)) + { + CcspTraceError(("%s: failed to pause Network Intelligence for speedtest\n", __FUNCTION__)); + ni_speedtest_thread_running = FALSE; + pthread_mutex_unlock(&ni_speedtest_mutex); + return NULL; + } + + while (!ni_speedtest_wake_early && waitStatus != ETIMEDOUT) + { + waitStatus = pthread_cond_timedwait(&ni_speedtest_cond, &ni_speedtest_mutex, &ni_speedtest_timeout); + if (waitStatus != 0 && waitStatus != ETIMEDOUT) + { + CcspTraceError(("%s: pthread_cond_timedwait failed, error=%d\n", __FUNCTION__, waitStatus)); + break; + } + } + timedOut = (waitStatus == ETIMEDOUT); + ni_speedtest_wake_early = FALSE; + + if (timedOut) + { + CcspTraceWarning(("%s: speedtest timeout expired, resuming Network Intelligence\n", __FUNCTION__)); + t2_event_d("IMP_CUJO_NI_SubscriberUnPauseTimeOut", 1); + } + if (!ni_qosd_enable(TRUE)) + { + CcspTraceError(("%s: failed to resume Network Intelligence after speedtest\n", __FUNCTION__)); + } + + ni_speedtest_thread_running = FALSE; + pthread_mutex_unlock(&ni_speedtest_mutex); + + return NULL; +} + +static BOOL ni_speedtest_trigger(uint32_t timeout) +{ + struct timespec ni_resume_timeout; + pthread_t tid; + int err; + + if (clock_gettime(CLOCK_REALTIME, &ni_resume_timeout) != 0) + { + CcspTraceError(("%s: clock_gettime failed, errno=%d\n", __FUNCTION__, errno)); + return FALSE; + } + ni_resume_timeout.tv_sec += timeout; + + pthread_mutex_lock(&ni_speedtest_mutex); + if (ni_speedtest_thread_running) + { + ni_speedtest_timeout = ni_resume_timeout; + pthread_cond_signal(&ni_speedtest_cond); + pthread_mutex_unlock(&ni_speedtest_mutex); + CcspTraceInfo(("%s: Network Intelligence already paused for speedtest, refreshed timeout\n", __FUNCTION__)); + return TRUE; + } + + ni_speedtest_timeout = ni_resume_timeout; + + ni_speedtest_wake_early = FALSE; + ni_speedtest_thread_running = TRUE; + + err = pthread_create(&tid, NULL, ni_speedtest_handler, NULL); + if (err != 0) + { + ni_speedtest_thread_running = FALSE; + pthread_mutex_unlock(&ni_speedtest_mutex); + CcspTraceError(("%s: failed to create speedtest timer thread, error=%d\n", __FUNCTION__, err)); + return FALSE; + } + pthread_mutex_unlock(&ni_speedtest_mutex); + return TRUE; +} + +static void ni_speedtest_complete(void) +{ + pthread_mutex_lock(&ni_speedtest_mutex); + if (ni_speedtest_thread_running) + { + ni_speedtest_wake_early = TRUE; + pthread_cond_signal(&ni_speedtest_cond); + } + pthread_mutex_unlock(&ni_speedtest_mutex); +} + +static BOOL speedtestGetTimeout(uint32_t *timeout) +{ + rbusValue_t value = NULL; + int ret; + + ret = rbus_get(rbus_handle, SPEEDTEST_TIMEOUT_DML, &value); + if (ret != RBUS_ERROR_SUCCESS) + { + CcspTraceError(("%s: rbus_get failed for %s, error=%d\n", __FUNCTION__, SPEEDTEST_TIMEOUT_DML, ret)); + if (value != NULL) + { + rbusValue_Release(value); + } + return FALSE; + } + + *timeout = rbusValue_GetUInt32(value); + rbusValue_Release(value); + + return TRUE; +} + +STATIC void speedtestEventReceiveHandler( + rbusHandle_t handle, + rbusEvent_t const* event, + rbusEventSubscription_t* subscription) +{ + rbusValue_t value; + uint32_t status; + uint32_t timeout; + + (void)handle; + (void)subscription; + + value = rbusObject_GetValue(event->data, NULL); + if (value == NULL) + { + CcspTraceError(("SpeedTest status event has no value\n")); + return; + } + + status = rbusValue_GetUInt32(value); + CcspTraceInfo(("%s: speedtest status event received, status=%u\n", __FUNCTION__, status)); + + if (!is_ni_enabled_and_activated()) + { + CcspTraceInfo(("%s: Network Intelligence is disabled or not activated, skipping speedtest event\n", __FUNCTION__)); + return; + } + + if (status == ST_TR181_STATUS_STARTING) + { + if (!speedtestGetTimeout(&timeout)) + { + CcspTraceError(("%s: failed to get speedtest unpause timeout, Network Intelligence will not be paused\n", __FUNCTION__)); + return; + } + if (timeout == 0) + { + CcspTraceInfo(("%s: speedtest unpause timeout is 0, skipping Network Intelligence pause\n", __FUNCTION__)); + return; + } + if (!ni_speedtest_trigger(timeout)) + { + CcspTraceError(("%s: Network Intelligence speedtest trigger failed, Network Intelligence will not be paused\n", __FUNCTION__)); + } + } + else if (status == ST_TR181_STATUS_COMPLETE) + { + ni_speedtest_complete(); + } +} +#endif + #if defined(WIFI_DATA_COLLECTION) || defined(NETWORK_INTELLIGENCE) static int touch_file(const char *filepath) { @@ -1584,6 +1805,14 @@ CosaSecurityInitialize CcspTraceError(("AdvSecurityEventConsumer: rbusEvent_Subscribe %s failed: %d\n", LEVL_DML, ret)); return ANSC_STATUS_FAILURE; } +#endif +#ifdef NETWORK_INTELLIGENCE + ret = rbusEvent_Subscribe(rbus_handle, SPEEDTEST_STATUS_DML, speedtestEventReceiveHandler, NULL, 0); + if(ret != RBUS_ERROR_SUCCESS) + { + CcspTraceError(("AdvSecurityEventConsumer: rbusEvent_Subscribe %s failed: %d\n", SPEEDTEST_STATUS_DML, ret)); + return ANSC_STATUS_FAILURE; + } #endif return returnStatus; } @@ -2568,24 +2797,6 @@ int advsec_webconfig_handle_blob(advsecurityparam_t *feature) if ( returnStatus != ANSC_STATUS_SUCCESS ) return SYSCFG_FAILURE; -#ifdef NETWORK_INTELLIGENCE - BOOL prev_ni_state = FALSE; - if (feature->network_intelligence_present) - { - prev_ni_state = g_pAdvSecAgent->pNetworkIntelligence->bActivate; - if (feature->network_intelligence_activate != g_pAdvSecAgent->pNetworkIntelligence->bActivate) - { - returnStatus = CosaSetSysCfgUlong(g_NetworkIntelligenceActivate, feature->network_intelligence_activate); - if ( returnStatus == ANSC_STATUS_SUCCESS ) - { - g_pAdvSecAgent->pNetworkIntelligence->bActivate = feature->network_intelligence_activate; - } - else - return SYSCFG_FAILURE; - } - } -#endif // NETWORK_INTELLIGENCE - if ( feature->fingerprint_enable != g_pAdvSecAgent->bEnable ) { if ( feature->fingerprint_enable ) @@ -2598,57 +2809,6 @@ int advsec_webconfig_handle_blob(advsecurityparam_t *feature) } else { -#ifdef NETWORK_INTELLIGENCE - if (feature->network_intelligence_present && - feature->network_intelligence_activate != prev_ni_state) - { - if (g_pAdvSecAgent->pAdvNetworkIntelligence_RFC->bEnable) - { - if (feature->network_intelligence_activate) - { - // -activateNI_R will restart cujo-agent and enable cujo-ni service - ret = v_secure_system(TEMP_DOWNLOAD_LOCATION"/usr/ccsp/advsec/start_adv_security.sh -activateNI_R &"); - if(ret != 0) - { - CcspTraceWarning(("Failure in executing command via v_secure_system. ret val: %d \n", ret)); - } - } - else - { - // -deactivateNI_R will restart cujo-agent and disable cujo-ni service - ret = v_secure_system(TEMP_DOWNLOAD_LOCATION"/usr/ccsp/advsec/start_adv_security.sh -deactivateNI_R &"); - if(ret != 0) - { - CcspTraceWarning(("Failure in executing command via v_secure_system. ret val: %d \n", ret)); - } - } - // -configure_features not required since cujo-agent restart will configure other features - return BLOB_EXEC_SUCCESS; - } - else - { - CcspTraceWarning(("%s: cannot activate NetworkIntelligence feature due to RFC is disabled\n", __FUNCTION__)); - if (feature->network_intelligence_activate) - { - // -activateNI will touch /tmp/advsec_networkintelligence_activated file, log only if RFC is enabled - ret = v_secure_system(TEMP_DOWNLOAD_LOCATION"/usr/ccsp/advsec/start_adv_security.sh -activateNI &"); - if(ret != 0) - { - CcspTraceWarning(("Failure in executing command via v_secure_system. ret val: %d \n", ret)); - } - } - else - { - // -deactivateNI will remove /tmp/advsec_networkintelligence_activated file, log only if RFC is enabled - ret = v_secure_system(TEMP_DOWNLOAD_LOCATION"/usr/ccsp/advsec/start_adv_security.sh -deactivateNI &"); - if(ret != 0) - { - CcspTraceWarning(("Failure in executing command via v_secure_system. ret val: %d \n", ret)); - } - } - } - } -#endif // NETWORK_INTELLIGENCE ret = v_secure_system(TEMP_DOWNLOAD_LOCATION"/usr/ccsp/advsec/start_adv_security.sh -configure_features &"); if(ret != 0) { @@ -2660,6 +2820,40 @@ int advsec_webconfig_handle_blob(advsecurityparam_t *feature) return BLOB_EXEC_SUCCESS; } +#ifdef NETWORK_INTELLIGENCE +int ni_webconfig_handle_blob(networkintelligenceparam_t *feature) +{ + ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; + + CcspTraceInfo(("Entering %s\n", __FUNCTION__)); + + if ( g_pAdvSecAgent == NULL || g_pAdvSecAgent->pNetworkIntelligence == NULL || + g_pAdvSecAgent->pAdvNetworkIntelligence_RFC == NULL ) + { + CcspTraceError(("%s: NetworkIntelligence datamodel is not initialized\n", __FUNCTION__)); + return ADVSEC_FAILURE; + } + + if ( feature->network_intelligence_activate == g_pAdvSecAgent->pNetworkIntelligence->bActivate ) + { + CcspTraceInfo(("%s: NetworkIntelligence activate already set to %d\n", + __FUNCTION__, feature->network_intelligence_activate)); + return BLOB_EXEC_SUCCESS; + } + + if ( feature->network_intelligence_activate ) + returnStatus = CosaNetworkIntelligenceActivate(g_pAdvSecAgent->pNetworkIntelligence); + else + returnStatus = CosaNetworkIntelligenceDeactivate(g_pAdvSecAgent->pNetworkIntelligence); + + if ( returnStatus != ANSC_STATUS_SUCCESS ) + return SYSCFG_FAILURE; + + CcspTraceInfo(("Done %s\n", __FUNCTION__)); + return BLOB_EXEC_SUCCESS; +} +#endif // NETWORK_INTELLIGENCE + ANSC_STATUS CosaAdvSecGetLoggingPeriod() { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; diff --git a/source/AdvSecurityDml/cosa_adv_security_internal.h b/source/AdvSecurityDml/cosa_adv_security_internal.h index d8cacd4..2389bc1 100644 --- a/source/AdvSecurityDml/cosa_adv_security_internal.h +++ b/source/AdvSecurityDml/cosa_adv_security_internal.h @@ -31,6 +31,7 @@ #include #include "ansc_platform.h" #include "ansc_string_util.h" +#include #define ADVSEC_MIN_LOG_TIMEOUT (60 * 1) #define ADVSEC_MAX_LOG_TIMEOUT (60 * 48) @@ -43,6 +44,8 @@ #define ADVSEC_LogLevel_VERBOSE 4 #define BUFLEN_1024 1024 #define PARTNER_REDIRECTORURL_PARAMNAME "Device.DeviceInfo.X_RDKCENTRAL-COM_Syndication.AdvsecRedirectorURL" +#define ST_TR181_STATUS_STARTING 1 +#define ST_TR181_STATUS_COMPLETE 5 typedef enum { ADVSEC_SAFEBROWSING=0, diff --git a/source/AdvSecurityDml/cosa_adv_security_webconfig.c b/source/AdvSecurityDml/cosa_adv_security_webconfig.c index 4cc4afd..38d4625 100644 --- a/source/AdvSecurityDml/cosa_adv_security_webconfig.c +++ b/source/AdvSecurityDml/cosa_adv_security_webconfig.c @@ -87,7 +87,11 @@ int advsec_webconfig_set_blobversion(char* subdoc, uint32_t version) void advsec_webconfig_init() { errno_t rc = -1; - char *sub_docs[SUBDOC_COUNT+1]= {ADVSEC_WEBCONFIG_SUBDOC_NAME,(char *) 0 }; + char *sub_docs[SUBDOC_COUNT+1]= {ADVSEC_WEBCONFIG_SUBDOC_NAME, +#ifdef NETWORK_INTELLIGENCE + NI_WEBCONFIG_SUBDOC_NAME, +#endif + (char *) 0 }; blobRegInfo *blobData; @@ -151,18 +155,9 @@ pErr advsec_webconfig_process_request(void *Data) CcspTraceInfo(("%s: advsec->subdoc_name is %s\n", __FUNCTION__, advsec->subdoc_name)); CcspTraceInfo(("%s: advsec->version is %lu\n", __FUNCTION__, (long)advsec->version)); CcspTraceInfo(("%s: advsec->transaction_id %lu\n",__FUNCTION__, (long) advsec->transaction_id)); - if (advsec->param->network_intelligence_present) - { - CcspTraceInfo(("%s: fingerprint_enable[%d], softflowd_enable[%d], safebrowsing_enable[%d], parental_control_activate[%d], privacy_protection_activate[%d], network_intelligence_activate[%d]\n", - __FUNCTION__, advsec->param->fingerprint_enable,advsec->param->softflowd_enable,advsec->param->safebrowsing_enable, - advsec->param->parental_control_activate, advsec->param->privacy_protection_activate, advsec->param->network_intelligence_activate)); - } - else - { - CcspTraceInfo(("%s: fingerprint_enable[%d], softflowd_enable[%d], safebrowsing_enable[%d], parental_control_activate[%d], privacy_protection_activate[%d]\n", - __FUNCTION__, advsec->param->fingerprint_enable,advsec->param->softflowd_enable,advsec->param->safebrowsing_enable, - advsec->param->parental_control_activate, advsec->param->privacy_protection_activate)); - } + CcspTraceInfo(("%s: fingerprint_enable[%d], softflowd_enable[%d], safebrowsing_enable[%d], parental_control_activate[%d], privacy_protection_activate[%d]\n", + __FUNCTION__, advsec->param->fingerprint_enable,advsec->param->softflowd_enable,advsec->param->safebrowsing_enable, + advsec->param->parental_control_activate, advsec->param->privacy_protection_activate)); rc = strcmp_s(ADVSEC_WEBCONFIG_SUBDOC_NAME, strlen(ADVSEC_WEBCONFIG_SUBDOC_NAME), advsec->subdoc_name, &ind); ERR_CHK(rc); @@ -207,7 +202,7 @@ pErr advsec_webconfig_process_request(void *Data) int advsec_webconfig_rollback() { // return 0 to notify framework when rollback is success - CcspTraceInfo((" Entering %s \n",__FUNCTION__)); + CcspTraceInfo(("Entering %s\n", __FUNCTION__)); int ret = 0; @@ -220,7 +215,7 @@ int advsec_webconfig_rollback() void advsec_webconfig_free_resources(void *arg) { - CcspTraceInfo((" Entering %s \n",__FUNCTION__)); + CcspTraceInfo(("Entering %s\n", __FUNCTION__)); execData *blob_exec_data = (execData*) arg; /* CID 158652: Dereference before null check */ diff --git a/source/AdvSecurityDml/cosa_adv_security_webconfig.h b/source/AdvSecurityDml/cosa_adv_security_webconfig.h index a78e9bc..3bf79c0 100644 --- a/source/AdvSecurityDml/cosa_adv_security_webconfig.h +++ b/source/AdvSecurityDml/cosa_adv_security_webconfig.h @@ -31,8 +31,15 @@ #include "webconfig_framework.h" #include "advsecurity_param.h" +#ifdef NETWORK_INTELLIGENCE +#include "networkintelligence_param.h" +#endif +#ifdef NETWORK_INTELLIGENCE +#define SUBDOC_COUNT 2 +#else #define SUBDOC_COUNT 1 +#endif #define BLOCK_SIZE 32 diff --git a/source/AdvSecurityDml/cosa_network_intelligence_webconfig.c b/source/AdvSecurityDml/cosa_network_intelligence_webconfig.c new file mode 100644 index 0000000..936a7fb --- /dev/null +++ b/source/AdvSecurityDml/cosa_network_intelligence_webconfig.c @@ -0,0 +1,123 @@ +/* + * + * Copyright 2016 Comcast Cable Communications Management, LLC + * + * 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. + * SPDX-License-Identifier: Apache-2.0 +*/ + +#include "cosa_network_intelligence_webconfig.h" +#include "webconfig_framework.h" +#include +#include +#include "safec_lib_common.h" + +/* CallBack API to execute Network Intelligence Blob request */ +pErr ni_webconfig_process_request(void *Data) +{ + pErr execRetVal = NULL; + errno_t rc = -1; + int ind = -1; + + execRetVal = (pErr) AnscAllocateMemory (sizeof(Err)); + if (execRetVal == NULL ) + { + CcspTraceError(("%s : AnscAllocateMemory failed\n",__FUNCTION__)); + return execRetVal; + } + + rc = memset_s(execRetVal, sizeof(Err), 0, sizeof(Err)); + ERR_CHK(rc); + + execRetVal->ErrorCode = BLOB_EXEC_SUCCESS; + + networkintelligencedoc_t *ni = (networkintelligencedoc_t *) Data ; + if( ni != NULL && ni->subdoc_name != NULL && ni->param != NULL ) + { + CcspTraceInfo(("%s: ni->subdoc_name is %s\n", __FUNCTION__, ni->subdoc_name)); + CcspTraceInfo(("%s: ni->version is %lu\n", __FUNCTION__, (long)ni->version)); + CcspTraceInfo(("%s: ni->transaction_id %lu\n",__FUNCTION__, (long) ni->transaction_id)); + CcspTraceInfo(("%s: network_intelligence_activate[%d]\n", + __FUNCTION__, ni->param->network_intelligence_activate)); + + rc = strcmp_s(NI_WEBCONFIG_SUBDOC_NAME, strlen(NI_WEBCONFIG_SUBDOC_NAME), ni->subdoc_name, &ind); + ERR_CHK(rc); + if((rc == EOK) && (ind == 0)) + { + int ret = ni_webconfig_handle_blob(ni->param); + + CcspTraceInfo(("%s: Return value = %d\n",__FUNCTION__, ret)); + + if ( ret == BLOB_EXEC_SUCCESS ) + { + if ( ni->param->network_intelligence_activate == TRUE ) + { + strncpy(execRetVal->ErrorMsg,"activated",sizeof(execRetVal->ErrorMsg)-1); + } + else + { + strncpy(execRetVal->ErrorMsg,"deactivated",sizeof(execRetVal->ErrorMsg)-1); + } + } + else + { + execRetVal->ErrorCode = ret; + } + } + else + { + CcspTraceWarning(("%s: Received an invalid subdoc: %s\n",__FUNCTION__, ni->subdoc_name)); + execRetVal->ErrorCode = SUBDOC_NOT_SUPPORTED; + } + } + else + { + CcspTraceWarning(("%s: Received null subdoc blob\n",__FUNCTION__)); + execRetVal->ErrorCode = NULL_BLOB_EXEC_POINTER; + } + + return execRetVal; +} + +/* Callback function to rollback when Network Intelligence blob execution fails */ +int ni_webconfig_rollback() +{ + // return 0 to notify framework when rollback is success + CcspTraceInfo(("Entering %s\n", __FUNCTION__)); + + int ret = 0; + + CcspTraceWarning(("%s: Something went wrong while processing webconfig request\n",__FUNCTION__)); + + return ret ; +} + +/* Callback function to free webconfig resources */ +void ni_webconfig_free_resources(void *arg) +{ + CcspTraceInfo(("Entering %s\n", __FUNCTION__)); + execData *blob_exec_data = (execData*) arg; + + if ( blob_exec_data != NULL ) + { + networkintelligencedoc_t *nd = (networkintelligencedoc_t *) blob_exec_data->user_data ; + + if ( nd != NULL ) + { + networkintelligencedoc_destroy(nd); + } + + AnscFreeMemory (blob_exec_data); + blob_exec_data = NULL ; + } +} diff --git a/source/AdvSecurityDml/cosa_network_intelligence_webconfig.h b/source/AdvSecurityDml/cosa_network_intelligence_webconfig.h new file mode 100644 index 0000000..dd65a95 --- /dev/null +++ b/source/AdvSecurityDml/cosa_network_intelligence_webconfig.h @@ -0,0 +1,37 @@ +/* + * + * Copyright 2016 Comcast Cable Communications Management, LLC + * + * 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. + * SPDX-License-Identifier: Apache-2.0 +*/ + +#ifndef _COSA_NETWORK_INTELLIGENCE_WEBCONFIG_H +#define _COSA_NETWORK_INTELLIGENCE_WEBCONFIG_H + +#include +#include +#include +#include +#include "ansc_status.h" +#include "ansc_platform.h" + +#include "webconfig_framework.h" +#include "networkintelligence_param.h" + +pErr ni_webconfig_process_request(void *Data); +int ni_webconfig_rollback(); +void ni_webconfig_free_resources(void *arg); +int ni_webconfig_handle_blob(networkintelligenceparam_t *feature); + +#endif diff --git a/source/AdvSecurityDml/networkintelligence_param.c b/source/AdvSecurityDml/networkintelligence_param.c new file mode 100644 index 0000000..bbadc66 --- /dev/null +++ b/source/AdvSecurityDml/networkintelligence_param.c @@ -0,0 +1,196 @@ +/* + * + * Copyright 2016 Comcast Cable Communications Management, LLC + * + * 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. + * SPDX-License-Identifier: Apache-2.0 +*/ + +#include +#include +#include +#include +#include "ccsp_trace.h" +#include "advsecurity_helpers.h" +#include "networkintelligence_param.h" +#include "ansc_platform.h" + +/*----------------------------------------------------------------------------*/ +/* Macros */ +/*----------------------------------------------------------------------------*/ +/* none */ +/*----------------------------------------------------------------------------*/ +/* Data Structures */ +/*----------------------------------------------------------------------------*/ +enum { + OK = HELPERS_OK, + OUT_OF_MEMORY = HELPERS_OUT_OF_MEMORY, + INVALID_FIRST_ELEMENT = HELPERS_INVALID_FIRST_ELEMENT, + MISSING_ENTRY = HELPERS_MISSING_WRAPPER, + INVALID_OBJECT, + INVALID_VERSION, +}; +/*----------------------------------------------------------------------------*/ +/* File Scoped Variables */ +/*----------------------------------------------------------------------------*/ +/* none */ +/*----------------------------------------------------------------------------*/ +/* Function Prototypes */ +/*----------------------------------------------------------------------------*/ +int process_networkintelligenceparams( networkintelligenceparam_t *e, msgpack_object_map *map ); +int process_networkintelligencedoc( networkintelligencedoc_t *nd, int num, ...); +/*----------------------------------------------------------------------------*/ +/* External Functions */ +/*----------------------------------------------------------------------------*/ +/* See networkintelligence_param.h for details. */ +networkintelligencedoc_t* networkintelligencedoc_convert( const void *buf, size_t len ) +{ + return comp_helper_convert( buf, len, sizeof(networkintelligencedoc_t), NI_WEBCONFIG_SUBDOC_NAME, + MSGPACK_OBJECT_MAP, true, + (process_fn_t) process_networkintelligencedoc, + (destroy_fn_t) networkintelligencedoc_destroy ); +} +/* See networkintelligence_param.h for details. */ +void networkintelligencedoc_destroy( networkintelligencedoc_t *nd ) +{ + if( NULL != nd ) + { + if( NULL != nd->subdoc_name ) + { + AnscFreeMemory ( nd->subdoc_name ); + } + if( NULL != nd->param ) + { + AnscFreeMemory ( nd->param ); + } + AnscFreeMemory ( nd ); + } +} +/* See networkintelligence_param.h for details. */ +const char* networkintelligencedoc_strerror( int errnum ) +{ + struct error_map { + int v; + const char *txt; + } map[] = { + { .v = OK, .txt = "No errors." }, + { .v = OUT_OF_MEMORY, .txt = "Out of memory." }, + { .v = INVALID_FIRST_ELEMENT, .txt = "Invalid first element." }, + { .v = INVALID_VERSION, .txt = "Invalid 'version' value." }, + { .v = INVALID_OBJECT, .txt = "Invalid 'value' array." }, + { .v = 0, .txt = NULL } + }; + int i = 0; + while( (map[i].v != errnum) && (NULL != map[i].txt) ) { i++; } + if( NULL == map[i].txt ) + { + CcspTraceError(("----%s----\n", __FUNCTION__)); + return "Unknown error."; + } + return map[i].txt; +} +/*----------------------------------------------------------------------------*/ +/* Internal functions */ +/*----------------------------------------------------------------------------*/ +/** + * Convert the msgpack map into the doc_t structure. + * + * @param e the entry pointer + * @param map the msgpack map pointer + * + * @return 0 on success, error otherwise + */ +int process_networkintelligenceparams( networkintelligenceparam_t *e, msgpack_object_map *map ) +{ + int left = map->size; + uint8_t objects_left = 0x01; + msgpack_object_kv *p; + p = map->ptr; + while( (0 < left--) && (0 != objects_left) ) + { + if( MSGPACK_OBJECT_STR == p->key.type ) + { + if( MSGPACK_OBJECT_BOOLEAN == p->val.type ) + { + if( 0 == match(p, "NetworkIntelligenceActivate") ) + { + e->network_intelligence_activate = p->val.via.boolean; + objects_left &= ~(1 << 0); + } + } + } + p++; + } + + if( 1 & objects_left ) { + } else { + errno = OK; + } + + return (0 == objects_left) ? 0 : -1; +} +int process_networkintelligencedoc( networkintelligencedoc_t *nd, int num, ... ) +{ +//To access the variable arguments use va_list + va_list valist; + va_start(valist, num);//start of variable argument loop + + msgpack_object *obj = va_arg(valist, msgpack_object *);//each usage of va_arg fn argument iterates by one time + msgpack_object *obj1 = va_arg(valist, msgpack_object *); + msgpack_object *obj2 = va_arg(valist, msgpack_object *); + msgpack_object *obj3 = va_arg(valist, msgpack_object *); + va_end(valist);//End of variable argument loop + + if( (NULL == obj) || (NULL == obj1) || (NULL == obj2) || (NULL == obj3) ) + { + CcspTraceError(("%s missing mandatory element(s) in subdoc\n", __FUNCTION__)); + return -1; + } + + if( (MSGPACK_OBJECT_MAP != obj->type) || + (MSGPACK_OBJECT_STR != obj1->type) || + (MSGPACK_OBJECT_POSITIVE_INTEGER != obj2->type) || + (MSGPACK_OBJECT_POSITIVE_INTEGER != obj3->type) ) + { + CcspTraceError(("%s unexpected element type(s) in subdoc\n", __FUNCTION__)); + return -1; + } + + msgpack_object_map *mapobj = &obj->via.map; + + nd->subdoc_name = strndup( obj1->via.str.ptr, obj1->via.str.size ); + if( NULL == nd->subdoc_name ) + { + CcspTraceError(("%s subdoc_name strndup failed\n", __FUNCTION__)); + return -1; + } + + nd->version = (uint32_t) obj2->via.u64; + nd->transaction_id = (uint16_t) obj3->via.u64; + + nd->param = (networkintelligenceparam_t *) AnscAllocateMemory( sizeof(networkintelligenceparam_t) ); + if( NULL == nd->param ) + { + CcspTraceError(("%s entries count AnscAllocateMemory failed\n", __FUNCTION__)); + return -1; + } + memset( nd->param, 0, sizeof(networkintelligenceparam_t)); + + if( 0 != process_networkintelligenceparams(nd->param, mapobj) ) + { + CcspTraceError(("%s failed\n", __FUNCTION__)); + return -1; + } + + return 0; +} diff --git a/source/AdvSecurityDml/networkintelligence_param.h b/source/AdvSecurityDml/networkintelligence_param.h new file mode 100644 index 0000000..e48e04b --- /dev/null +++ b/source/AdvSecurityDml/networkintelligence_param.h @@ -0,0 +1,63 @@ +/* + * + * Copyright 2016 Comcast Cable Communications Management, LLC + * + * 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. + * SPDX-License-Identifier: Apache-2.0 +*/ + +#ifndef __NETWORKINTELLIGENCE_PARAM_H__ +#define __NETWORKINTELLIGENCE_PARAM_H__ +#include +#include +#include + +#define NI_WEBCONFIG_SUBDOC_NAME "networkintelligence" + +typedef struct +{ + bool network_intelligence_activate; + +} networkintelligenceparam_t; + +typedef struct { + networkintelligenceparam_t *param; + char * subdoc_name; + uint32_t version; + uint16_t transaction_id; +} networkintelligencedoc_t; +/** + * This function converts a msgpack buffer into a networkintelligencedoc_t + * structure if possible. + * + * @param buf the buffer to convert + * @param len the length of the buffer in bytes + * + * @return NULL on error, success otherwise + */ +networkintelligencedoc_t* networkintelligencedoc_convert( const void *buf, size_t len ); +/** + * This function destroys a networkintelligencedoc_t object. + * + * @param d the networkintelligencedoc to destroy + */ +void networkintelligencedoc_destroy( networkintelligencedoc_t *d ); +/** + * This function returns a general reason why the conversion failed. + * + * @param errnum the errno value to inspect + * + * @return the constant string (do not alter or free) describing the error + */ +const char* networkintelligencedoc_strerror( int errnum ); +#endif diff --git a/source/AdvSecurityDml/plugin_main.c b/source/AdvSecurityDml/plugin_main.c index ffe2c57..00d225c 100644 --- a/source/AdvSecurityDml/plugin_main.c +++ b/source/AdvSecurityDml/plugin_main.c @@ -111,6 +111,8 @@ COSA_Init pPlugInfo->RegisterFunction(pPlugInfo->hContext, "NetworkIntelligence_GetParamBoolValue", NetworkIntelligence_GetParamBoolValue); pPlugInfo->RegisterFunction(pPlugInfo->hContext, "NetworkIntelligence_SetParamBoolValue", NetworkIntelligence_SetParamBoolValue); + + pPlugInfo->RegisterFunction(pPlugInfo->hContext, "NetworkIntelligence_SetParamStringValue", NetworkIntelligence_SetParamStringValue); #endif // NETWORK_INTELLIGENCE pPlugInfo->RegisterFunction(pPlugInfo->hContext, "WifiDataCollection_RFC_GetParamBoolValue", WifiDataCollection_RFC_GetParamBoolValue); diff --git a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityDmlTest.cpp b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityDmlTest.cpp index 3525b14..791fe8c 100644 --- a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityDmlTest.cpp +++ b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityDmlTest.cpp @@ -41,6 +41,7 @@ class CcspAdvSecurityDmlTestFixture : public ::testing::Test { g_syseventMock = new SyseventMock(); g_webconfigFwMock = new webconfigFwMock(); g_anscWrapperApiMock = new AnscWrapperApiMock(); + g_telemetryMock = new telemetryMock(); } void TearDown() override { @@ -60,6 +61,7 @@ class CcspAdvSecurityDmlTestFixture : public ::testing::Test { delete g_syseventMock; delete g_webconfigFwMock; delete g_anscWrapperApiMock; + delete g_telemetryMock; g_syscfgMock = nullptr; g_securewrapperMock = nullptr; g_msgpackMock = nullptr; @@ -76,6 +78,7 @@ class CcspAdvSecurityDmlTestFixture : public ::testing::Test { g_syseventMock = nullptr; g_webconfigFwMock = nullptr; g_anscWrapperApiMock = nullptr; + g_telemetryMock = nullptr; } }; diff --git a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityInternalTest.cpp b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityInternalTest.cpp index e8695fc..357bf1c 100644 --- a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityInternalTest.cpp +++ b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityInternalTest.cpp @@ -43,6 +43,7 @@ class CcspAdvSecurityInternalTestFixture : public ::testing::Test { g_syseventMock = new SyseventMock(); g_webconfigFwMock = new webconfigFwMock(); g_anscWrapperApiMock = new AnscWrapperApiMock(); + g_telemetryMock = new telemetryMock(); } void TearDown() override { @@ -62,6 +63,7 @@ class CcspAdvSecurityInternalTestFixture : public ::testing::Test { delete g_syseventMock; delete g_webconfigFwMock; delete g_anscWrapperApiMock; + delete g_telemetryMock; g_syscfgMock = nullptr; g_securewrapperMock = nullptr; g_msgpackMock = nullptr; @@ -78,6 +80,7 @@ class CcspAdvSecurityInternalTestFixture : public ::testing::Test { g_syseventMock = nullptr; g_webconfigFwMock = nullptr; g_anscWrapperApiMock = nullptr; + g_telemetryMock = nullptr; } }; @@ -1441,6 +1444,419 @@ TEST_F(CcspAdvSecurityInternalTestFixture, CosaRabidSetDNSCacheSize) free(g_pAdvSecAgent); } +#ifdef NETWORK_INTELLIGENCE +#include + +extern "C" void speedtestEventReceiveHandler(rbusHandle_t handle, rbusEvent_t const* event, rbusEventSubscription_t* subscription); +/* Internal SpeedTest timer state exposed (non-static in unit-test builds + * via the STATIC macro) purely so tests can synchronize with the + * asynchronous timer thread. No test-only function is defined in + * production source for this. */ +extern "C" pthread_mutex_t ni_speedtest_mutex; +extern "C" BOOL ni_speedtest_thread_running; + +static const char *g_speedtestNIEnabledPath = "/tmp/advsec_networkintelligence_enabled"; +static const char *g_speedtestNIActivatedPath = "/tmp/advsec_networkintelligence_activated"; + +static void CreateSpeedtestNIEnabledAndActivated(void) +{ + FILE *file = fopen(g_speedtestNIEnabledPath, "w"); + if (file) fclose(file); + file = fopen(g_speedtestNIActivatedPath, "w"); + if (file) fclose(file); +} + +static void RemoveSpeedtestNIEnabledAndActivated(void) +{ + remove(g_speedtestNIEnabledPath); + remove(g_speedtestNIActivatedPath); +} + +/* Test-only helper: reads the SpeedTest timer thread's running state + * under its production mutex. */ +static bool IsSpeedtestThreadRunning(void) +{ + BOOL running; + + pthread_mutex_lock(&ni_speedtest_mutex); + running = ni_speedtest_thread_running; + pthread_mutex_unlock(&ni_speedtest_mutex); + return running ? true : false; +} + +/* Polls IsSpeedtestThreadRunning() until the SpeedTest timer thread + * reaches the desired state or maxWaitMs elapses. The thread's work + * (mocked v_secure_system calls) completes in microseconds, so this + * bounds test time while avoiding a fixed, potentially-flaky sleep. */ +static void WaitForSpeedtestThreadState(bool running, int maxWaitMs) +{ + int waited = 0; + while (IsSpeedtestThreadRunning() != running && waited < maxWaitMs) + { + usleep(2000); + waited += 2; + } +} + +TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Starting_PausesAndCompletes_ResumesNI) +{ + int marker = 0; + int timeoutMarker = 0; + int completeMarker = 5; + rbusValue_t value = (rbusValue_t)▮ + rbusValue_t timeoutValue = (rbusValue_t)&timeoutMarker; + rbusValue_t completeValue = (rbusValue_t)&completeMarker; + rbusEvent_t event = {}; + CreateSpeedtestNIEnabledAndActivated(); + + EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _)) + .Times(2) + .WillOnce(Return(value)) + .WillOnce(Return(completeValue)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value)) + .Times(1) + .WillOnce(Return(ST_TR181_STATUS_STARTING)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(completeValue)) + .Times(1) + .WillOnce(Return(ST_TR181_STATUS_COMPLETE)); + EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _)) + .Times(1) + .WillOnce(DoAll(SetArgPointee<2>(timeoutValue), Return(RBUS_ERROR_SUCCESS))); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(timeoutValue)) + .Times(1) + .WillOnce(Return(86400)); + EXPECT_CALL(*g_rbusMock, rbusValue_Release(timeoutValue)) + .Times(1); + EXPECT_CALL(*g_securewrapperMock, v_secure_system(HasSubstr("cujo-ni-cli"), _)) + .Times(2) + .WillRepeatedly(Return(0)); + + /* status=1: starts the timer thread, which pauses NI immediately. */ + speedtestEventReceiveHandler(NULL, &event, NULL); + WaitForSpeedtestThreadState(true, 200); + EXPECT_TRUE(IsSpeedtestThreadRunning()); + + /* status=5: wakes the thread early so it resumes NI and exits. */ + speedtestEventReceiveHandler(NULL, &event, NULL); + WaitForSpeedtestThreadState(false, 500); + EXPECT_FALSE(IsSpeedtestThreadRunning()); + + RemoveSpeedtestNIEnabledAndActivated(); +} + +TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Starting_PauseFails_ClearsRunningState) +{ + int marker = 0; + int timeoutMarker = 0; + rbusValue_t value = (rbusValue_t)▮ + rbusValue_t timeoutValue = (rbusValue_t)&timeoutMarker; + rbusEvent_t event = {}; + CreateSpeedtestNIEnabledAndActivated(); + + EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _)) + .Times(1) + .WillOnce(Return(value)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value)) + .Times(1) + .WillOnce(Return(ST_TR181_STATUS_STARTING)); + EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _)) + .Times(1) + .WillOnce(DoAll(SetArgPointee<2>(timeoutValue), Return(RBUS_ERROR_SUCCESS))); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(timeoutValue)) + .Times(1) + .WillOnce(Return(86400)); + EXPECT_CALL(*g_rbusMock, rbusValue_Release(timeoutValue)) + .Times(1); + /* Simulate cujo-ni-cli failing (non-zero exit status) on the pause + * attempt. The thread must still clear ni_speedtest_thread_running + * so future SpeedTest cycles are not permanently blocked. */ + EXPECT_CALL(*g_securewrapperMock, v_secure_system(HasSubstr("cujo-ni-cli"), _)) + .Times(1) + .WillOnce(Return(256)); + + speedtestEventReceiveHandler(NULL, &event, NULL); + WaitForSpeedtestThreadState(false, 500); + EXPECT_FALSE(IsSpeedtestThreadRunning()); + + RemoveSpeedtestNIEnabledAndActivated(); +} + + +TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Starting_DuplicateStart_RefreshesTimeout) +{ + int marker = 0; + int timeoutMarker = 0; + int completeMarker = 5; + rbusValue_t value = (rbusValue_t)▮ + rbusValue_t timeoutValue = (rbusValue_t)&timeoutMarker; + rbusValue_t completeValue = (rbusValue_t)&completeMarker; + rbusEvent_t event = {}; + CreateSpeedtestNIEnabledAndActivated(); + + EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _)) + .Times(3) + .WillOnce(Return(value)) + .WillOnce(Return(value)) + .WillOnce(Return(completeValue)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value)) + .Times(2) + .WillRepeatedly(Return(ST_TR181_STATUS_STARTING)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(completeValue)) + .Times(1) + .WillOnce(Return(ST_TR181_STATUS_COMPLETE)); + /* Timeout is fetched again on the duplicate STARTING event, since + * ni_speedtest_trigger() now refreshes the running timer's deadline + * instead of ignoring the event. */ + EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _)) + .Times(2) + .WillRepeatedly(DoAll(SetArgPointee<2>(timeoutValue), Return(RBUS_ERROR_SUCCESS))); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(timeoutValue)) + .Times(2) + .WillRepeatedly(Return(86400)); + EXPECT_CALL(*g_rbusMock, rbusValue_Release(timeoutValue)) + .Times(2); + /* Only ONE pause + ONE resume, even though status=1 fires twice: + * the duplicate STARTING event only refreshes the deadline, it does + * not re-pause Network Intelligence or spawn a new thread. */ + EXPECT_CALL(*g_securewrapperMock, v_secure_system(HasSubstr("cujo-ni-cli"), _)) + .Times(2) + .WillRepeatedly(Return(0)); + + speedtestEventReceiveHandler(NULL, &event, NULL); + WaitForSpeedtestThreadState(true, 200); + EXPECT_TRUE(IsSpeedtestThreadRunning()); + + /* Duplicate status=1 while already running: refreshes the deadline + * on the existing thread, no new pause, no new thread. */ + speedtestEventReceiveHandler(NULL, &event, NULL); + EXPECT_TRUE(IsSpeedtestThreadRunning()); + + speedtestEventReceiveHandler(NULL, &event, NULL); + WaitForSpeedtestThreadState(false, 500); + EXPECT_FALSE(IsSpeedtestThreadRunning()); + + RemoveSpeedtestNIEnabledAndActivated(); +} + +TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Starting_NIDisabled_NoAction) +{ + int marker = 0; + int completeMarker = 5; + rbusValue_t value = (rbusValue_t)▮ + rbusValue_t completeValue = (rbusValue_t)&completeMarker; + rbusEvent_t event = {}; + RemoveSpeedtestNIEnabledAndActivated(); + + EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _)) + .Times(2) + .WillOnce(Return(value)) + .WillOnce(Return(completeValue)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value)) + .Times(1) + .WillOnce(Return(ST_TR181_STATUS_STARTING)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(completeValue)) + .Times(1) + .WillOnce(Return(ST_TR181_STATUS_COMPLETE)); + /* NI is disabled: speedtestEventReceiveHandler now returns before + * ever fetching the timeout, for any status. */ + EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _)) + .Times(0); + EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _)) + .Times(0); + + /* NI is disabled: the top-level is_ni_enabled_and_activated() check + * in speedtestEventReceiveHandler skips the event entirely, so + * ni_speedtest_thread_running never becomes TRUE. */ + speedtestEventReceiveHandler(NULL, &event, NULL); + EXPECT_FALSE(IsSpeedtestThreadRunning()); + + speedtestEventReceiveHandler(NULL, &event, NULL); + EXPECT_FALSE(IsSpeedtestThreadRunning()); +} + +TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Starting_NIEnabledButNotActivated_NoAction) +{ + int marker = 0; + int completeMarker = 5; + rbusValue_t value = (rbusValue_t)▮ + rbusValue_t completeValue = (rbusValue_t)&completeMarker; + rbusEvent_t event = {}; + remove(g_speedtestNIActivatedPath); + FILE *file = fopen(g_speedtestNIEnabledPath, "w"); + if (file) fclose(file); + + EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _)) + .Times(2) + .WillOnce(Return(value)) + .WillOnce(Return(completeValue)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value)) + .Times(1) + .WillOnce(Return(ST_TR181_STATUS_STARTING)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(completeValue)) + .Times(1) + .WillOnce(Return(ST_TR181_STATUS_COMPLETE)); + /* NI is enabled but not activated: still gated out before ever + * fetching the timeout. */ + EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _)) + .Times(0); + EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _)) + .Times(0); + + /* NI is enabled but not activated: the top-level + * is_ni_enabled_and_activated() check skips the event entirely. */ + speedtestEventReceiveHandler(NULL, &event, NULL); + EXPECT_FALSE(IsSpeedtestThreadRunning()); + + speedtestEventReceiveHandler(NULL, &event, NULL); + EXPECT_FALSE(IsSpeedtestThreadRunning()); + + remove(g_speedtestNIEnabledPath); +} + +TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_StartingWithZeroTimeout_NoAction) +{ + int marker = 0; + int timeoutMarker = 0; + rbusValue_t value = (rbusValue_t)▮ + rbusValue_t timeoutValue = (rbusValue_t)&timeoutMarker; + rbusEvent_t event = {}; + CreateSpeedtestNIEnabledAndActivated(); + + EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _)) + .Times(1) + .WillOnce(Return(value)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value)) + .Times(1) + .WillOnce(Return(ST_TR181_STATUS_STARTING)); + EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _)) + .Times(1) + .WillOnce(DoAll(SetArgPointee<2>(timeoutValue), Return(RBUS_ERROR_SUCCESS))); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(timeoutValue)) + .Times(1) + .WillOnce(Return(0)); + EXPECT_CALL(*g_rbusMock, rbusValue_Release(timeoutValue)) + .Times(1); + EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _)) + .Times(0); + + speedtestEventReceiveHandler(NULL, &event, NULL); + + EXPECT_FALSE(IsSpeedtestThreadRunning()); + + RemoveSpeedtestNIEnabledAndActivated(); +} + +TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Starting_GetTimeoutFailsWithValue_ReleasesRbusValue) +{ + int marker = 0; + int timeoutMarker = 0; + rbusValue_t value = (rbusValue_t)▮ + rbusValue_t timeoutValue = (rbusValue_t)&timeoutMarker; + rbusEvent_t event = {}; + CreateSpeedtestNIEnabledAndActivated(); + + EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _)) + .Times(1) + .WillOnce(Return(value)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value)) + .Times(1) + .WillOnce(Return(ST_TR181_STATUS_STARTING)); + /* rbus_get() fails but still populates a non-NULL value (a real + * rbus behavior in some implementations, e.g. partial/cached state + * before returning an error). speedtestGetTimeout() must release it + * instead of leaking it. */ + EXPECT_CALL(*g_rbusMock, rbus_get(_, StrEq("Device.IP.Diagnostics.X_RDK_SpeedTest.SubscriberUnPauseTimeOut"), _)) + .Times(1) + .WillOnce(DoAll(SetArgPointee<2>(timeoutValue), Return(RBUS_ERROR_BUS_ERROR))); + EXPECT_CALL(*g_rbusMock, rbusValue_Release(timeoutValue)) + .Times(1); + EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _)) + .Times(0); + + speedtestEventReceiveHandler(NULL, &event, NULL); + + EXPECT_FALSE(IsSpeedtestThreadRunning()); + + RemoveSpeedtestNIEnabledAndActivated(); +} + +TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Complete_NoThreadRunning_NoAction) +{ + int marker = 0; + rbusValue_t value = (rbusValue_t)▮ + rbusEvent_t event = {}; + CreateSpeedtestNIEnabledAndActivated(); + + EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _)) + .Times(1) + .WillOnce(Return(value)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value)) + .Times(1) + .WillOnce(Return(ST_TR181_STATUS_COMPLETE)); + EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _)) + .Times(0); + + speedtestEventReceiveHandler(NULL, &event, NULL); + + RemoveSpeedtestNIEnabledAndActivated(); +} + +TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Complete_NIDisabled_NoAction) +{ + int marker = 0; + rbusValue_t value = (rbusValue_t)▮ + rbusEvent_t event = {}; + RemoveSpeedtestNIEnabledAndActivated(); + + EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _)) + .Times(1) + .WillOnce(Return(value)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value)) + .Times(1) + .WillOnce(Return(ST_TR181_STATUS_COMPLETE)); + EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _)) + .Times(0); + + /* NI disabled: the top-level is_ni_enabled_and_activated() check now + * gates COMPLETE the same as STARTING. */ + speedtestEventReceiveHandler(NULL, &event, NULL); +} + +TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_NullValue_NoAction) +{ + rbusEvent_t event = {}; + + EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _)) + .Times(1) + .WillOnce(Return((rbusValue_t)NULL)); + EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _)) + .Times(0); + + speedtestEventReceiveHandler(NULL, &event, NULL); +} + +TEST_F(CcspAdvSecurityInternalTestFixture, SpeedTest_Status_Other_NoAction) +{ + int marker = 0; + rbusValue_t value = (rbusValue_t)▮ + rbusEvent_t event = {}; + CreateSpeedtestNIEnabledAndActivated(); + + EXPECT_CALL(*g_rbusMock, rbusObject_GetValue(_, _)) + .Times(1) + .WillOnce(Return(value)); + EXPECT_CALL(*g_rbusMock, rbusValue_GetUInt32(value)) + .Times(1) + .WillOnce(Return(2)); + EXPECT_CALL(*g_securewrapperMock, v_secure_system(_, _)) + .Times(0); + + speedtestEventReceiveHandler(NULL, &event, NULL); + + RemoveSpeedtestNIEnabledAndActivated(); +} +#endif + TEST_F(CcspAdvSecurityInternalTestFixture, CosaAdvPCInit) { const char *AdvParentalControlRFCEnabled = "Adv_PCRFCEnable"; diff --git a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.cpp b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.cpp index a690f88..342b12e 100644 --- a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.cpp +++ b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.cpp @@ -34,3 +34,4 @@ cjsonMock *g_cjsonMock = NULL; SyseventMock *g_syseventMock = NULL; webconfigFwMock *g_webconfigFwMock = NULL; AnscWrapperApiMock * g_anscWrapperApiMock = NULL; +telemetryMock *g_telemetryMock = NULL; diff --git a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.h b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.h index f73fbf9..1223968 100644 --- a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.h +++ b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityMock.h @@ -43,6 +43,7 @@ #include #include #include +#include extern SyscfgMock *g_syscfgMock; extern SecureWrapperMock *g_securewrapperMock; @@ -60,6 +61,7 @@ extern cjsonMock *g_cjsonMock; extern SyseventMock *g_syseventMock; extern webconfigFwMock *g_webconfigFwMock; extern AnscWrapperApiMock *g_anscWrapperApiMock; +extern telemetryMock *g_telemetryMock; using namespace std; using std::experimental::filesystem::exists; diff --git a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityWebconfigTest.cpp b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityWebconfigTest.cpp index 597d14b..a1e000c 100644 --- a/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityWebconfigTest.cpp +++ b/source/test/CcspAdvSecurityDmlTest/CcspAdvSecurityWebconfigTest.cpp @@ -37,6 +37,7 @@ class CcspAdvSecurityWebconfigTestFixture : public ::testing::Test { g_syseventMock = new SyseventMock(); g_webconfigFwMock = new webconfigFwMock(); g_anscWrapperApiMock = new AnscWrapperApiMock(); + g_telemetryMock = new telemetryMock(); } void TearDown() override { @@ -56,6 +57,7 @@ class CcspAdvSecurityWebconfigTestFixture : public ::testing::Test { delete g_syseventMock; delete g_webconfigFwMock; delete g_anscWrapperApiMock; + delete g_telemetryMock; g_syscfgMock = nullptr; g_securewrapperMock = nullptr; g_msgpackMock = nullptr; @@ -72,6 +74,7 @@ class CcspAdvSecurityWebconfigTestFixture : public ::testing::Test { g_syseventMock = nullptr; g_webconfigFwMock = nullptr; g_anscWrapperApiMock = nullptr; + g_telemetryMock = nullptr; } }; @@ -165,8 +168,8 @@ TEST_F(CcspAdvSecurityWebconfigTestFixture, advsec_webconfig_init) { .Times(1) .WillOnce(Return(0)); EXPECT_CALL(*g_safecLibMock, _strcpy_s_chk(_, _, _, _)) - .Times(1) - .WillOnce(Return(0)); + .Times(SUBDOC_COUNT) + .WillRepeatedly(Return(0)); EXPECT_CALL(*g_webconfigFwMock, register_sub_docs(_, _, _, _)) .Times(1); diff --git a/source/test/CcspAdvSecurityDmlTest/Makefile.am b/source/test/CcspAdvSecurityDmlTest/Makefile.am index 6cfdb0a..49db1db 100644 --- a/source/test/CcspAdvSecurityDmlTest/Makefile.am +++ b/source/test/CcspAdvSecurityDmlTest/Makefile.am @@ -45,6 +45,8 @@ CcspAdvSecurityDmlTest_gtest_bin_SOURCES = CcspAdvSecurityMock.cpp \ ${top_builddir}/source/AdvSecurityDml/advsecurity_helpers.c \ ${top_builddir}/source/AdvSecurityDml/advsecurity_param.c \ ${top_builddir}/source/AdvSecurityDml/cosa_adv_security_webconfig.c \ + ${top_builddir}/source/AdvSecurityDml/cosa_network_intelligence_webconfig.c \ + ${top_builddir}/source/AdvSecurityDml/networkintelligence_param.c \ ${top_builddir}/source/AdvSecurityDml/plugin_main.c \ gtest_main.cpp @@ -55,6 +57,7 @@ CcspAdvSecurityDmlTest_gtest_bin_LDADD = \ $(HOME)/usr/local/lib/libmock_secure_wrapper.la \ $(HOME)/usr/local/lib/libmock_msgpack.la \ $(HOME)/usr/local/lib/libmock_safec_lib.la \ + $(HOME)/usr/local/lib/libmock_telemetry.la \ $(HOME)/usr/local/lib/libmock_webconfigframework.la \ $(HOME)/usr/local/lib/libmock_base64.la \ $(HOME)/usr/local/lib/libmock_rbus.la \