Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ no) DHCP_MANAGER_ENABLE=false ;;
esac],[DHCP_MANAGER_ENABLE=false])
AM_CONDITIONAL([DHCP_MANAGER_ENABLE], [test x$DHCP_MANAGER_ENABLE = xtrue])

AC_ARG_ENABLE([onestack],
[ --enable-onestack Turn on OneStack utility ],
[case "${enableval}" in
yes) ONESTACK_ENABLE=true ;;
no) ONESTACK_ENABLE=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-onestack]) ;;
esac],[ONESTACK_ENABLE=true])
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OneStack utility defaults to enabled (ONESTACK_ENABLE=true) while most other optional features in configure.ac default to disabled (false). For example, dhcp_manager (line 136), socketExampleEnable (line 113), and wbCfgTestAppEnable (line 94) all default to false. Unless there's a specific reason for OneStack to be enabled by default, consider changing this to false for consistency with other optional utilities.

Copilot uses AI. Check for mistakes.
AM_CONDITIONAL([ONESTACK_ENABLE], [test x$ONESTACK_ENABLE = xtrue])

AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])

Expand Down Expand Up @@ -186,6 +195,8 @@ AM_COND_IF([RDKSCHEDULER_TESTAPP_ENABLE], [AC_CONFIG_FILES([source/RdkSchdeuler_

AM_COND_IF([SOCKET_EXAMPLE_ENABLE], [AC_CONFIG_FILES([source/Socket_Example/Makefile])])

AM_COND_IF([ONESTACK_ENABLE], [AC_CONFIG_FILES([source/onestack/Makefile])])

AC_SUBST(GTEST_CORE_NET_LIB)

AC_SUBST(UNIT_TEST_DOCKER_SUPPORT)
Expand Down
6 changes: 5 additions & 1 deletion source/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ if SOCKET_EXAMPLE_ENABLE
SOCKET_EXAMPLE = Socket_Example
endif

if ONESTACK_ENABLE
ONESTACK = onestack
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to something else like set_device_stackmode, apply_device_stackmode etc.

endif

if DHCP_MANAGER_ENABLE
DHCP_CLIENT_UTILS_EXAMPLE =
else
Expand All @@ -53,5 +57,5 @@ endif
if UNIT_TEST_DOCKER_SUPPORT
SUBDIRS = test
else
SUBDIRS = Psmcli parcon LTime ServiceCtrl TimeConv webcfg_decoder MemFrag_Calc $(SETLED) $(MULTIPART_UTIL) $(BRIDGE_UTIL) $(WBCFG_TEST) $(DHCP_CLIENT_UTILS_EXAMPLE) msgq_util EventSubscription FwBankInfo $(RDKSCHEDULER_TESTAPP) $(SOCKET_EXAMPLE)
SUBDIRS = Psmcli parcon LTime ServiceCtrl TimeConv webcfg_decoder MemFrag_Calc $(ONESTACK) $(SETLED) $(MULTIPART_UTIL) $(BRIDGE_UTIL) $(WBCFG_TEST) $(DHCP_CLIENT_UTILS_EXAMPLE) msgq_util EventSubscription FwBankInfo $(RDKSCHEDULER_TESTAPP) $(SOCKET_EXAMPLE)
endif
27 changes: 27 additions & 0 deletions source/onestack/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
##########################################################################
# If not stated otherwise in this file or this component's Licenses.txt
# file the following copyright and licenses apply:
#
# Copyright 2026 RDK Management
#
# Licensed under the Apache License, Version 2.0 (the "License");

Check failure on line 7 in source/onestack/Makefile.am

View workflow job for this annotation

GitHub Actions / call-fossid-workflow / Fossid Annotate PR

FossID License Issue Detected

Source code with 'GPL-2.0' license found in local file 'source/onestack/Makefile.am' (Match: unofficial-openjdk/openjdk/7-b24, 11 lines, url: https://github.com/unofficial-openjdk/openjdk/archive/refs/tags/jdk7-b24.tar.gz, file: jaxp/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Makefile.inc)
# 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.
##########################################################################
AM_CFLAGS = -Wall -Werror

bin_PROGRAMS = onestack

onestack_SOURCES = onestack.c onestack_log.c

onestack_CPPFLAGS = -I$(top_srcdir)/source/onestack

onestack_LDADD = -lsyscfg -lrdkloggers -lhal_platform
152 changes: 152 additions & 0 deletions source/onestack/onestack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "onestack.h"
#include "onestack_log.h"
#include "syscfg/syscfg.h"
#include "platform_hal.h"

#if defined(_ONESTACK_PRODUCT_REQ_)
#define BUFLEN_32 32
#define BUFLEN_256 256
#define MAX_RETRY 3
#define RETRY_DELAY_SEC 1
#define PARTNER_ID_FILE "/nvram/.partner_ID"

/**
* @brief Trim trailing newline from string
* @param str String to trim
*/
static inline void trim_newline(char *str)
{
size_t len = strlen(str);
if (len > 0 && str[len - 1] == '\n')
{
str[len - 1] = '\0';
}
}

/**
* @brief Get partner ID with fallback mechanism
* @param pValue Buffer to store the partner ID
* @param size Size of the buffer
* @return 0 on success, -1 on failure
*/
int getpartnerid(char *pValue, int size)
{
FILE *fp = NULL;
char buffer[BUFLEN_256] = {0};
int retry;

if (!pValue || size <= 0)
{
ONESTACK_ERROR("%s: Invalid parameters (pValue=%p, size=%d)\n", __FUNCTION__, pValue, size);
return -1;
}

ONESTACK_DEBUG("%s: Starting partner ID retrieval\n", __FUNCTION__);

// 1. Try HAL API with retries
for (retry = 0; retry < MAX_RETRY; retry++)
{
ONESTACK_DEBUG("%s: Attempting HAL API call (attempt %d/%d)\n", __FUNCTION__, retry + 1, MAX_RETRY);
if (platform_hal_getFactoryPartnerId(pValue) == 0 && pValue[0] != '\0')
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The platform_hal_getFactoryPartnerId function is called without validating if the buffer size is sufficient. The function is passed pValue which could have a size smaller than what the HAL function expects or writes. The HAL function doesn't receive the size parameter, so it cannot perform bounds checking. If the HAL function writes more data than the buffer can hold, this could result in a buffer overflow. Consider checking the minimum required buffer size for platform_hal_getFactoryPartnerId or ensuring that pValue is always large enough.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In our test devices, this may always return comcast eventhough activate partnerid is set to someother. Please check /nvram/.partnerID if not exists go with the HAL

{
ONESTACK_INFO("%s: Partner ID retrieved from HAL API: %s (attempt %d)\n", __FUNCTION__, pValue, retry + 1);
return 0;
}
if (retry < MAX_RETRY - 1)
{
sleep(RETRY_DELAY_SEC);
}
}
ONESTACK_WARN("%s: HAL API failed after %d retries, trying file method\n", __FUNCTION__, MAX_RETRY);

// 2. Try reading from file
if (access(PARTNER_ID_FILE, R_OK) == 0)
{
ONESTACK_DEBUG("%s: Attempting to read from file: %s\n", __FUNCTION__, PARTNER_ID_FILE);
fp = fopen(PARTNER_ID_FILE, "r");
if (fp)
{
if (fgets(buffer, sizeof(buffer), fp))
{
trim_newline(buffer);

if (buffer[0] != '\0')
{
strncpy(pValue, buffer, size - 1);
pValue[size - 1] = '\0';
fclose(fp);
ONESTACK_INFO("%s: Partner ID retrieved from file: %s\n", __FUNCTION__, pValue);
return 0;
}
Comment on lines +73 to +84
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file read operation doesn't validate the content length before copying. If the file contains data longer than BUFLEN_256 (256 bytes), fgets will read up to 255 bytes plus null terminator, which is safe. However, the subsequent strncpy to pValue uses 'size - 1' which could be smaller than the buffer content. While this is handled correctly with null termination, there's no validation that the partner ID read from the file is within expected bounds or contains only valid characters. Consider adding validation to ensure the partner ID contains only expected characters (alphanumeric, hyphens, underscores) to prevent potential issues with downstream consumers.

Copilot uses AI. Check for mistakes.
}
fclose(fp);
}
else
{
ONESTACK_WARN("%s: Failed to open file: %s\n", __FUNCTION__, PARTNER_ID_FILE);
}
}
else
{
ONESTACK_DEBUG("%s: File not accessible: %s, trying syscfg\n", __FUNCTION__, PARTNER_ID_FILE);
}

// 3. Fallback to syscfg
ONESTACK_DEBUG("%s: Attempting syscfg_get for PartnerID\n", __FUNCTION__);
if (syscfg_get(NULL, "PartnerID", pValue, size) == 0 && pValue[0] != '\0')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This util expected to run even before syscfg. so this won't work.

{
ONESTACK_INFO("%s: Partner ID retrieved from syscfg: %s\n", __FUNCTION__, pValue);
return 0;
}

ONESTACK_ERROR("%s: Failed to retrieve partner ID from all sources (HAL/File/Syscfg)\n", __FUNCTION__);
return -1;
}

int main(int argc, char *argv[])
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The argc and argv parameters in main are unused when ONESTACK_PRODUCT_REQ is defined. While this is not technically an error, consider marking them as unused with (void)argc; (void)argv; or using compiler-specific attributes to suppress warnings, as this is a common practice seen in other utilities like source/FwBankInfo/FwBank_Info.c which doesn't use its main parameters at all.

Copilot uses AI. Check for mistakes.
{
char partnerId[BUFLEN_256] = {0};
bool isBci = false;

// Initialize RDK logger
if (!onestack_log_init())
{
printf("Warning: Logging initialization failed, continuing with console output\n");
}

ONESTACK_INFO("OneStack Partner ID Utility started\n");
printf("OneStack Partner ID Utility\n");
printf("===========================\n\n");

if (getpartnerid(partnerId, sizeof(partnerId)) == 0)
{
isBci = (strcmp(partnerId, "comcast-business") == 0);

ONESTACK_INFO("Partner ID: %s | Is BCI: %s\n", partnerId, isBci ? "Yes" : "No");
printf("\n[SUCCESS] Partner ID: %s\n", partnerId);
printf("[INFO] Partner is %sComcast Business (BCI)\n", isBci ? "" : "NOT ");

onestack_log_deinit();
return 0;
}

ONESTACK_ERROR("Failed to retrieve Partner ID\n");
fprintf(stderr, "\n[FAILED] Unable to retrieve Partner ID\n");

onestack_log_deinit();
Comment on lines +133 to +140
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main function does not check the return value of onestack_log_deinit before returning. If deinitalization fails at line 133 or 140, the failure is silently ignored, which could lead to resource cleanup issues. Consider logging a warning if deinitalization fails.

Suggested change
onestack_log_deinit();
return 0;
}
ONESTACK_ERROR("Failed to retrieve Partner ID\n");
fprintf(stderr, "\n[FAILED] Unable to retrieve Partner ID\n");
onestack_log_deinit();
if (!onestack_log_deinit())
{
fprintf(stderr, "Warning: Logging deinitialization failed\n");
}
return 0;
}
ONESTACK_ERROR("Failed to retrieve Partner ID\n");
fprintf(stderr, "\n[FAILED] Unable to retrieve Partner ID\n");
if (!onestack_log_deinit())
{
fprintf(stderr, "Warning: Logging deinitialization failed\n");
}

Copilot uses AI. Check for mistakes.
return 1;
}

#else

int main(int argc, char *argv[])
{
fprintf(stderr, "ERROR: OneStack utility is not enabled (_ONESTACK_PRODUCT_REQ_ not defined)\n");
return 1;
}

#endif
24 changes: 24 additions & 0 deletions source/onestack/onestack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef _COMMON_ONESTACK_H_
#define _COMMON_ONESTACK_H_

#include <stdbool.h>

#ifdef _ONESTACK_PRODUCT_REQ_

/**
* @brief Get partner ID with fallback mechanism
*
* This function attempts to retrieve the partner ID using the following priority:
* 1. HAL API (platform_hal_getFactoryPartnerId) with 3 retries
* 2. Read from /nvram/.partner_ID file
* 3. Read from syscfg (PartnerID)
*
* @param pValue Buffer to store the partner ID
* @param size Size of the buffer
* @return 0 on success, -1 on failure
*/
int getpartnerid(char *pValue, int size);

#endif

#endif /* _COMMON_ONESTACK_H_ */
46 changes: 46 additions & 0 deletions source/onestack/onestack_log.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* If not stated otherwise in this file or this component's Licenses.txt file the
* following copyright and licenses apply:
*
* Copyright 2026 RDK Management
*
* Licensed under the Apache License, Version 2.0 (the "License");

Check failure on line 7 in source/onestack/onestack_log.c

View workflow job for this annotation

GitHub Actions / call-fossid-workflow / Fossid Annotate PR

FossID License Issue Detected

Source code with 'GPL-2.0' license found in local file 'source/onestack/onestack_log.c' (Match: lede-project/source/17.01.0-rc1, 13 lines, url: https://github.com/lede-project/source/archive/refs/tags/v17.01.0-rc1.tar.gz, file: package/network/utils/owipcalc/src/owipcalc.c)
* 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.
*/

#include <stdio.h>
#include "onestack_log.h"

bool onestack_log_init(void)
{
if (rdk_logger_init(DEBUG_INI_PATH) != 0)
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value comparison is inconsistent with codebase conventions. In source/ServiceCtrl/servicecontrol_log.c:10, the pattern is to compare rdk_logger_init return value against RDK_SUCCESS, not against 0. The current comparison may work but doesn't follow the established pattern where RDK_SUCCESS is the symbolic constant used for success checks.

Copilot uses AI. Check for mistakes.
{
fprintf(stderr, "Warning: RDK logger initialization failed for %s\n", DEBUG_INI_PATH);
return false;
}

ONESTACK_INFO("%s: Logging initialized successfully\n", __FUNCTION__);
return true;
}

bool onestack_log_deinit(void)
{
ONESTACK_DEBUG("%s: Deinitializing logging\n", __FUNCTION__);

if (rdk_logger_deinit() != 0)
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value comparison is inconsistent with codebase conventions. In source/ServiceCtrl/servicecontrol_log.c:27, the pattern is to compare rdk_logger_deinit return value against RDK_SUCCESS, not against 0. The current comparison may work but doesn't follow the established pattern where RDK_SUCCESS is the symbolic constant used for success checks.

Copilot uses AI. Check for mistakes.
{
fprintf(stderr, "Warning: RDK logger deinitialization failed\n");
return false;
}

return true;
}
50 changes: 50 additions & 0 deletions source/onestack/onestack_log.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* If not stated otherwise in this file or this component's Licenses.txt file the
* following copyright and licenses apply:
*
* Copyright 2026 RDK Management
*
* 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.
*/

#ifndef _ONESTACK_LOG_H_
#define _ONESTACK_LOG_H_

#include <stdbool.h>
#include "rdk_debug.h"

#define LOG_MODULE "LOG.RDK.ONESTACK"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need a separate log file, similar to apply system defaults, log to consolelog.txt.

#define DEBUG_INI_PATH "/etc/debug.ini"

// Logging macros
#define ONESTACK_LOG(level, ...) \
RDK_LOG(level, LOG_MODULE, __VA_ARGS__)

#define ONESTACK_ERROR(...) ONESTACK_LOG(RDK_LOG_ERROR, __VA_ARGS__)
#define ONESTACK_WARN(...) ONESTACK_LOG(RDK_LOG_WARN, __VA_ARGS__)
#define ONESTACK_INFO(...) ONESTACK_LOG(RDK_LOG_INFO, __VA_ARGS__)
#define ONESTACK_DEBUG(...) ONESTACK_LOG(RDK_LOG_DEBUG, __VA_ARGS__)

/**
* @brief Initialize OneStack logging
* @return true on success, false on failure
*/
bool onestack_log_init(void);

/**
* @brief Deinitialize OneStack logging
* @return true on success, false on failure
*/
bool onestack_log_deinit(void);

#endif /* _ONESTACK_LOG_H_ */
Loading