Skip to content

RDKB-62810,RDKB-62812:Create Virtual Interface for voice and initialize DHCP#25

Open
Amaresh-Kotekal wants to merge 19 commits intordkcentral:developfrom
Amaresh-Kotekal:develop
Open

RDKB-62810,RDKB-62812:Create Virtual Interface for voice and initialize DHCP#25
Amaresh-Kotekal wants to merge 19 commits intordkcentral:developfrom
Amaresh-Kotekal:develop

Conversation

@Amaresh-Kotekal
Copy link

Reason for change:Creating the virtual interface and initializing the dhcp
Test Procedure: verify the interface creation and IP assignment.
Risks: High
Priority: P1

Amaresh-Kotekal and others added 7 commits November 27, 2025 00:24
Reason for change:Added the new entry for virual mta interface
Test Procedure: verify the logic and functionality
Risks: Low
Priority: P1
Reason for change:Added the new entry for mac Vlan interface
Test Procedure: verify the logic and functionality
Risks: High
Priority: P1
Reason for change:Added the new entry for mac vlan interface
Test Procedure: verify the logic and functionality
Risks: High
Priority: P1
Reason for change:Added the new entry for mac vlan interface
Test Procedure: verify the logic and functionality
Risks: High
Priority: P1
Reason for change:Added the new entry for mac vlan interface
Test Procedure: verify the logic and functionality
Risks: High
Priority: P1
Reason for change:Added the new entry for virual mta interface
Test Procedure: verify the logic and functionality
Risks: High
Priority: P1
Reason for change:Added the new entry for virual mta interface
Test Procedure: verify the logic and functionality
Risks: High
Priority: P1
Copilot AI review requested due to automatic review settings January 12, 2026 22:59
@Amaresh-Kotekal Amaresh-Kotekal requested review from a team as code owners January 12, 2026 22:59
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds functionality to create a virtual macvlan interface for voice services and initialize DHCP on that interface for the SCXF10 platform. The implementation reads voice configuration from syscfg, creates a macvlan interface with a MAC address read from factory data, and starts DHCP client using rbus communication.

Changes:

  • Added new rbus API wrapper functions for DHCP configuration
  • Implemented macvlan interface creation with MAC address assignment from factory data
  • Integrated interface creation into the MTA sysevent thread on WAN state transitions

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 22 comments.

File Description
source/TR-181/middle_layer_src/cosa_x_cisco_com_mta_internal.c Added readMacAddress() and createMtaInterface() functions; integrated calls into Mta_Sysevent_thread for WAN up events
source/TR-181/middle_layer_src/cosa_rbus_apis.h New header defining rbus API wrapper function prototypes and parameter value type enum
source/TR-181/middle_layer_src/cosa_rbus_apis.c New implementation of rbus API wrappers for initializing rbus handle and enabling DHCPv4
source/TR-181/middle_layer_src/Makefile.am Added cosa_rbus_apis.c to build sources

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


#define DHCPv4_VOICE_SUPPORT_PARAM "dmsb.voicesupport.Interface.IP.DHCPV4Interface"

rbusHandle_t voiceRbusHandle = NULL;
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The voiceRbusHandle is a global variable that is initialized in initRbusHandle() but never cleaned up. If the component is unloaded or terminated, rbus_close() should be called to properly release the rbus handle and associated resources, preventing resource leaks.

Copilot uses AI. Check for mistakes.
Comment on lines 30 to 128
static rbusValueType_t convertRbusDataType(paramValueType_t paramType)
{
rbusValueType_t rbusType = RBUS_NONE;
switch (paramType)
{
case BOOLEAN_PARAM:
rbusType = RBUS_BOOLEAN;
break;
case STRING_PARAM:
rbusType = RBUS_STRING;
break;
default:
CcspTraceWarning(("%s: Unsupported param type %d\n", __FUNCTION__, paramType));
break;
}
return rbusType;
}

static void setParamInDhcpMgr(const char * pParamName, const char * pParamValue, paramValueType_t paramType)
{
if (voiceRbusHandle == NULL || pParamName == NULL || pParamValue == NULL)
{
CcspTraceError(("%s: Invalid rbus handle or NULL parameter\n", __FUNCTION__));
return;
}
int iRet = -1;
rbusValue_t rbusValue;
rbusValueType_t rbusType = convertRbusDataType(paramType);
if (rbusType == RBUS_NONE)
{
CcspTraceError(("%s: Unsupported param type %d for param %s\n", __FUNCTION__, paramType, pParamName));
return;
}

rbusValue_Init(&rbusValue);
if (false == rbusValue_SetFromString(rbusValue, rbusType, pParamValue))
{
CcspTraceError(("%s: rbusValue_SetFromString failed for param %s with value %s\n", __FUNCTION__, pParamName, pParamValue));
rbusValue_Release(rbusValue);
return;
}

iRet = rbus_set(voiceRbusHandle, pParamName, rbusValue, NULL);
if (iRet != RBUS_ERROR_SUCCESS)
{
CcspTraceError(("%s: rbus_set failed for param %s with error code %d\n", __FUNCTION__, pParamName, iRet));
}
else
{
CcspTraceInfo(("%s: rbus_set successful for param %s with value %s\n", __FUNCTION__, pParamName, pParamValue));
}
rbusValue_Release(rbusValue);
}

void initRbusHandle(void)
{
rbusError_t rbusReturn = RBUS_ERROR_SUCCESS;
if (voiceRbusHandle != NULL)
{
CcspTraceInfo(("%s: rbus handle already initialized\n", __FUNCTION__));
return;
}
rbusReturn = rbus_open(&voiceRbusHandle, "VoiceSupportMtaInterface");
if (rbusReturn != RBUS_ERROR_SUCCESS)
{
CcspTraceError(("%s: rbus_open failed with error code %d\n", __FUNCTION__, rbusReturn));
return;
}
CcspTraceInfo(("%s: rbus_open successful\n", __FUNCTION__));
}

void enableDhcpv4ForMta(const char * pIfaceName)
{
int iRetPsmGet = CCSP_SUCCESS;
char cBaseParam[32] = {0};
char cParamName[64] = {0};
char *pParamValue= NULL;

iRetPsmGet = PSM_Get_Record_Value2(bus_handle, cSubsystem, DHCPv4_VOICE_SUPPORT_PARAM, NULL, &pParamValue);
if (iRetPsmGet != CCSP_SUCCESS)
{
CcspTraceError(("%s: PSM_Get_Record_Value2 failed for param %s with error code %d\n", __FUNCTION__, DHCPv4_VOICE_SUPPORT_PARAM,
iRetPsmGet));
return;
}
else
{
CcspTraceInfo(("%s: PSM_Get_Record_Value2 successful for param %s with value %s\n", __FUNCTION__, DHCPv4_VOICE_SUPPORT_PARAM,
pParamValue));
snprintf(cBaseParam, sizeof(cBaseParam), "%s",pParamValue);
((CCSP_MESSAGE_BUS_INFO *)bus_handle)->freefunc((char *)pParamValue);
}

snprintf(cParamName, sizeof(cParamName), "%s.Enable", cBaseParam);
setParamInDhcpMgr(cParamName, "true", BOOLEAN_PARAM);

snprintf(cParamName, sizeof(cParamName), "%s.Interface", cBaseParam);
setParamInDhcpMgr(cParamName, pIfaceName, STRING_PARAM);
}
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The new rbus API functions in this file lack test coverage. Given that the repository has comprehensive automated testing for similar functionality, these new functions should have corresponding unit tests to verify their behavior with various input conditions and error scenarios.

Copilot uses AI. Check for mistakes.

#define DHCPv4_VOICE_SUPPORT_PARAM "dmsb.voicesupport.Interface.IP.DHCPV4Interface"

rbusHandle_t voiceRbusHandle = NULL;
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The voiceRbusHandle is a global variable that can be accessed from multiple threads. The Mta_Sysevent_thread function calls initRbusHandle() and createMtaInterface() which both use this global variable, but there is no mutex or other synchronization mechanism to protect concurrent access. This could lead to race conditions if multiple threads attempt to initialize or use the rbus handle simultaneously.

Copilot uses AI. Check for mistakes.
Comment on lines 215 to 254
char cMtaIfaceDhcpV4Enabled[32] = {0};
char cVoiceSupportIfaceName[32] = {0};
char cMtaInterfaceMac[32] = {0};
char cWanIfname[32] = {0};
syscfg_get(NULL, "VoiceSupport_Enabled", cVoiceSupportEnabled, sizeof(cVoiceSupportEnabled));
syscfg_get(NULL, "VoiceSupport_IfaceName", cVoiceSupportIfaceName, sizeof(cVoiceSupportIfaceName));

if (cVoiceSupportEnabled[0] == '\0' || strcmp(cVoiceSupportEnabled, "true") != 0) {
CcspTraceError(("%s:%d, VoiceSupport_Enabled is false or not set, skipping MTA interface creation\n", __FUNCTION__, __LINE__));
return;
}
if (cVoiceSupportIfaceName[0] == '\0') {
CcspTraceError(("%s:%d, mtaIface not set in syscfg, using default mta0\n", __FUNCTION__, __LINE__));
strcpy_s(cVoiceSupportIfaceName, sizeof(cVoiceSupportIfaceName), "mta0");
}
//Read the mac address from platform_hal_GetMTAMacAddress API once it is implemented
readMacAddress(cMtaInterfaceMac);
if (strlen(cMtaInterfaceMac) == 0 || cMtaInterfaceMac[0] == '\0') {
CcspTraceError(("%s: readMacAddress failed to get MAC address\n", __FUNCTION__));
return;
}
CcspTraceInfo(("%s:%d, MTA MacVlan Mac is %s\n", __FUNCTION__, __LINE__, cMtaInterfaceMac));
syscfg_get(NULL, "wan_physical_ifname", cWanIfname, sizeof(cWanIfname));
CcspTraceInfo(("%s:%d, WAN Physical Ifname is %s\n", __FUNCTION__, __LINE__, cWanIfname));
if (cWanIfname[0] == '\0')
strcpy_s(cWanIfname, sizeof(cWanIfname), "erouter0");

//Create the macVlan
CcspTraceInfo(("%s:%d, Creating macVlan interface %s with mac %s\n", __FUNCTION__, __LINE__, cVoiceSupportIfaceName, cMtaInterfaceMac));
char cCmd[2048] = {0};
snprintf(cCmd, sizeof(cCmd), "ip link add link %s name %s type macvlan mode bridge", cWanIfname, cVoiceSupportIfaceName);
system(cCmd);
snprintf(cCmd, sizeof(cCmd), "ip link set dev %s address %s", cVoiceSupportIfaceName, cMtaInterfaceMac);
system(cCmd);
snprintf(cCmd, sizeof(cCmd), "ip link set dev %s up", cVoiceSupportIfaceName);
system(cCmd);
CcspTraceInfo(("%s:%d, Created macVlan interface %s\n", __FUNCTION__, __LINE__, cVoiceSupportIfaceName));


syscfg_get(NULL, "VoiceSupport_Mode",cMtaIfaceDhcpV4Enabled, sizeof(cMtaIfaceDhcpV4Enabled));
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The variable name "cMtaIfaceDhcpV4Enabled" is misleading. The variable is used to store the voice support mode ("IPv4_Only" or "Dual_Stack"), not a boolean flag indicating whether DHCPv4 is enabled. A more accurate name would be "cVoiceSupportMode" or "cMtaIfaceMode" to reflect what it actually contains.

Copilot uses AI. Check for mistakes.
setParamInDhcpMgr(cParamName, pIfaceName, STRING_PARAM);
}

//void subscribeDhcpClientEvents()
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

This commented-out function declaration should either be implemented if it's intended to be part of this feature, or removed entirely to keep the code clean. Leaving commented-out code can cause confusion about whether the functionality is planned, incomplete, or deprecated.

Suggested change
//void subscribeDhcpClientEvents()

Copilot uses AI. Check for mistakes.
@Amaresh-Kotekal Amaresh-Kotekal changed the title RDKB-62812:Create Virtual Interface for voice and initialize DHCP RDKB-62810,RDKB-62812:Create Virtual Interface for voice and initialize DHCP Jan 12, 2026
@Amaresh-Kotekal
Copy link
Author

Amaresh-Kotekal commented Jan 12, 2026

Is this a Bug or a User Story (US)?
=====> yes. It is a US

If it is a User Story:

Please list all dependent PRs from other components, if any.
rdkcentral/utopia#171
rdkcentral/provisioning-and-management#168
rdkcentral/dhcp-manager#53
https://gerrit.teamccp.com/#/q/topic:xf10-26Q1_sprint+(status:open+OR+status:merged)

The commit message must include both the User Story ticket and the Subtask ticket --> addressed

All changes related to the User Story must be squashed and merged in a single commit.

Do not raise pull requests for partial User Story changes.

Has the code development for the User Story been completed? --> Not yet

If yes, please share the Gerrit topic or list all dependent PRs across components, including any meta-layer changes.
Is there a validation log available in the Jira ticket for verifying builds with the updated generic-srcrev.inc across all platforms?

If yes, please share the links to the validation comments.

Reason for change:Creating the virtual interface and initializing the dhcp
Test Procedure: verify the interface creation and IP assignment.
Risks: High
Priority: P1
Reason for change:Subscribing for DHCP events via R-BUS
Test Procedure: verify the DHCP message is received or not
Risks: High
Priority: P1
Copilot AI review requested due to automatic review settings January 14, 2026 00:44
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 20 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

static void createMtaInterface(void)
{
char cVoiceSupportEnabled[8] = {0};
char cMtaIfaceDhcpV4Enabled[32] = {0};
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The variable name cMtaIfaceDhcpV4Enabled is misleading. Based on its usage (lines 316-322), it actually stores the VoiceSupport_Mode configuration value (e.g., "IPv4_Only" or "Dual_Stack"), not a simple enabled/disabled boolean. Consider renaming to something more descriptive like cVoiceSupportMode or cMtaIfaceMode to better reflect its actual content and purpose.

Copilot uses AI. Check for mistakes.
syscfg_get(NULL, "VoiceSupport_Mode",cMtaIfaceDhcpV4Enabled, sizeof(cMtaIfaceDhcpV4Enabled));
if (0 == strcmp(cMtaIfaceDhcpV4Enabled, VOICE_SUPPORT_MODE_IPV4_ONLY) || 0 == strcmp(cMtaIfaceDhcpV4Enabled, VOICE_SUPPORT_MODE_DUAL_STACK)) {
CcspTraceInfo(("%s:%d, Starting udhcpc on MTA interface %s\n", __FUNCTION__, __LINE__, cVoiceSupportIfaceName));
subscribeDhcpClientEvents();
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

This line uses a tab character for indentation while the surrounding code uses spaces. This creates inconsistent indentation. Please use consistent whitespace formatting (spaces) to match the rest of the file.

Suggested change
subscribeDhcpClientEvents();
subscribeDhcpClientEvents();

Copilot uses AI. Check for mistakes.
Comment on lines 33 to 40
/*
* @brief Convert parameter value type to rbus value type.
*
* @param[in] paramType Parameter value type to be converted.
* @return Corresponding rbus value type.
*/

static rbusValueType_t convertRbusDataType(paramValueType_t paramType)
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The function documentation comment starting with /* should use /** to be consistent with Doxygen-style documentation used elsewhere.

Copilot uses AI. Check for mistakes.
Comment on lines 308 to 313
snprintf(cCmd, sizeof(cCmd), "ip link add link %s name %s type macvlan mode bridge", cWanIfname, cVoiceSupportIfaceName);
system(cCmd);
snprintf(cCmd, sizeof(cCmd), "ip link set dev %s address %s", cVoiceSupportIfaceName, cMtaInterfaceMac);
system(cCmd);
snprintf(cCmd, sizeof(cCmd), "ip link set dev %s up", cVoiceSupportIfaceName);
system(cCmd);
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

Using system() to execute shell commands with variables derived from syscfg is a security risk. The variables cWanIfname, cVoiceSupportIfaceName, and cMtaInterfaceMac could potentially contain shell metacharacters that lead to command injection. Although these values come from configuration, it's best practice to validate/sanitize the input or use safer alternatives like direct system calls or properly escaped commands.

Copilot uses AI. Check for mistakes.
Comment on lines 210 to 217
rbusValue_t rbusValue = rbusObject_GetValue(pRbusEvent->data, "Ifname");
snprintf(sDhcpEvtData.cIfaceName, sizeof(sDhcpEvtData.cIfaceName), "%s", rbusValue_GetString(rbusValue, NULL));
CcspTraceInfo(("%s: DHCP %s event for interface %s\n", __FUNCTION__,
(sDhcpEvtData.dhcpVersion == DHCP_IPv4) ? "IPv4" : "IPv6", sDhcpEvtData.cIfaceName));

rbusValue = rbusObject_GetValue(pRbusEvent->data, "MsgType");
sDhcpEvtData.dhcpMsgType = (DHCP_MESSAGE_TYPE)rbusValue_GetUInt32(rbusValue);
CcspTraceInfo(("%s: DHCP Message Type %d\n", __FUNCTION__, sDhcpEvtData.dhcpMsgType));
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The dhcpClientEventsHandler function does not check if rbusObject_GetValue returns NULL before using the rbusValue. If the expected fields are not present in the event data, this could lead to a NULL pointer dereference. Add NULL checks after each rbusObject_GetValue call.

Copilot uses AI. Check for mistakes.
Comment on lines +51 to +59
/*
* @brief Retrieve interface index information for the MTA interface.
*
* This function retrieves Interface index information for the MTA interface
* from the PSM (Persistent Storage Manager) and logs the retrieved value.
* It reads the parameter "dmsb.voicesupport.Interface.IP.DHCPV4Interface"
* from the PSM and stores it in a static variable for later use. If the
* retrieval fails, it logs an error message.
*/
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The comment block starts with /* on line 51 instead of /** which is inconsistent with the Doxygen-style documentation used for other functions in this file (lines 62, 72, 86). Use /** to maintain consistency.

Copilot uses AI. Check for mistakes.
Comment on lines 211 to 233
static void readMacAddress (char * pMacAddress)
{
FILE *pFILE = fopen("/tmp/factory_nvram.data", "r");
if (pFILE != NULL)
{
char cLine[128] = {0};
while (fgets(cLine, sizeof(cLine), pFILE) != NULL)
{
if (strncmp(cLine, "EMTA ",5) == 0)
{
char *pMac = cLine + 5;
pMac[strcspn(pMac, "\n")] = 0; // Remove newline character
strcpy_s(pMacAddress, 32, pMac);
break;
}
}
fclose(pFILE);
}
else
{
CcspTraceError(("%s: Failed to open /tmp/factory_nvram.data\n", __FUNCTION__));
}
}
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The readMacAddress function does not handle the case where the file is successfully opened but the "EMTA " line is not found. In this scenario, pMacAddress would remain uninitialized or contain its previous value, potentially leading to the use of an invalid MAC address. Consider initializing pMacAddress to an empty string at the start of the function or logging an error if the expected line is not found after reading the entire file.

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +39
DHCP_IPv4=0,
DHCP_IPv6,
DHCP_BOTH,
DHCP_NONE
}DhcpVersion;

Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The DhcpVersion type is used but the enum values use inconsistent casing. The enum name is "DhcpVersion" (camelCase with capital D and V) but the values like DHCP_IPv4 use all uppercase with underscores, and IPv4/IPv6 have inconsistent internal casing. Consider using consistent naming conventions throughout, such as DHCP_IPV4, DHCP_IPV6, etc.

Suggested change
DHCP_IPv4=0,
DHCP_IPv6,
DHCP_BOTH,
DHCP_NONE
}DhcpVersion;
DHCP_IPV4 = 0,
DHCP_IPV6,
DHCP_BOTH,
DHCP_NONE
} DhcpVersion;
/* Backward compatibility for older enum value names */
#define DHCP_IPv4 DHCP_IPV4
#define DHCP_IPv6 DHCP_IPV6

Copilot uses AI. Check for mistakes.
CosaMTAInitializeEthWanProv(pMyObject);
}
#if defined (SCXF10)
CcspTraceWarning(("%s:%d, current_wan_state up, Initializing MTA Inteface \n",__FUNCTION__,__LINE__));
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

Spelling error: "Inteface" should be "Interface".

Suggested change
CcspTraceWarning(("%s:%d, current_wan_state up, Initializing MTA Inteface \n",__FUNCTION__,__LINE__));
CcspTraceWarning(("%s:%d, current_wan_state up, Initializing MTA Interface \n",__FUNCTION__,__LINE__));

Copilot uses AI. Check for mistakes.
Comment on lines 308 to 313
snprintf(cCmd, sizeof(cCmd), "ip link add link %s name %s type macvlan mode bridge", cWanIfname, cVoiceSupportIfaceName);
system(cCmd);
snprintf(cCmd, sizeof(cCmd), "ip link set dev %s address %s", cVoiceSupportIfaceName, cMtaInterfaceMac);
system(cCmd);
snprintf(cCmd, sizeof(cCmd), "ip link set dev %s up", cVoiceSupportIfaceName);
system(cCmd);
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The system() calls to create and configure the macvlan interface do not check return values. If any of these commands fail (e.g., interface already exists, insufficient permissions, invalid parameters), the failure will be silent and subsequent operations may fail in unexpected ways. Consider checking the return value of system() calls and logging errors or taking appropriate action when commands fail.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 19 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 239 to 242
syscfg_get(NULL, "VoiceSupport_IfaceName",cVoiceSupportIfaceName, sizeof(cVoiceSupportIfaceName));
syscfg_get(NULL, "VoiceSupport_Mode",cVoiceSupportMode, sizeof(cVoiceSupportMode));
syscfg_get(NULL, "VoiceSupport_Enabled", cVoiceSupportEnabled, sizeof(cVoiceSupportEnabled));

Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

Missing validation for syscfg_get return values. The syscfg_get calls on lines 239-241 don't check their return values to determine if the retrieval was successful. If syscfg_get fails, the buffers may contain garbage or empty values, leading to incorrect behavior. While there are checks for empty strings, explicit return value checking would make the error handling more robust.

Suggested change
syscfg_get(NULL, "VoiceSupport_IfaceName",cVoiceSupportIfaceName, sizeof(cVoiceSupportIfaceName));
syscfg_get(NULL, "VoiceSupport_Mode",cVoiceSupportMode, sizeof(cVoiceSupportMode));
syscfg_get(NULL, "VoiceSupport_Enabled", cVoiceSupportEnabled, sizeof(cVoiceSupportEnabled));
int rc;
rc = syscfg_get(NULL, "VoiceSupport_IfaceName", cVoiceSupportIfaceName, sizeof(cVoiceSupportIfaceName));
if (rc != 0)
{
CcspTraceError(("%s:%d, syscfg_get failed for key VoiceSupport_IfaceName (rc=%d)\n", __FUNCTION__, __LINE__, rc));
}
rc = syscfg_get(NULL, "VoiceSupport_Mode", cVoiceSupportMode, sizeof(cVoiceSupportMode));
if (rc != 0)
{
CcspTraceError(("%s:%d, syscfg_get failed for key VoiceSupport_Mode (rc=%d)\n", __FUNCTION__, __LINE__, rc));
}
rc = syscfg_get(NULL, "VoiceSupport_Enabled", cVoiceSupportEnabled, sizeof(cVoiceSupportEnabled));
if (rc != 0)
{
CcspTraceError(("%s:%d, syscfg_get failed for key VoiceSupport_Enabled (rc=%d)\n", __FUNCTION__, __LINE__, rc));
}

Copilot uses AI. Check for mistakes.
{
//Create the macVlan
CcspTraceInfo(("%s:%d, Creating macVlan interface %s with mac %s\n", __FUNCTION__, __LINE__, pVoiceSupportIfaceName, cMtaInterfaceMac));
char cCmd[2048] = {0};
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

The buffer size for cCmd is excessively large (2048 bytes) when constructing simple commands that use interface names and MAC addresses which have known maximum lengths. This wastes stack space. Consider using a more appropriate size like 256 or 512 bytes, which is sufficient for these commands.

Suggested change
char cCmd[2048] = {0};
char cCmd[256] = {0};

Copilot uses AI. Check for mistakes.
Comment on lines 299 to 328
#if 0
typedef struct
{
char intfName[VOICE_IFNAME_LEN];
uint8_t isPhyUp; /* link state (1=up) */

/* DHCPv4 */
uint8_t isIpv4Up; /* IPv4 address valid */
char ipv4Addr[VOICE_IPV4_ADDR_LEN]; /* IP or CIDR, e.g., "192.0.2.10/24" */
char v4NextServerIp[VOICE_IPV4_ADDR_LEN]; /* BOOTP siaddr */
char v4ServerHostName[VOICE_STRMAX_128]; /* BOOTP sname or opt 66 */
char v4BootFileName[VOICE_STRMAX_128]; /* BOOTP file or opt 67 */
char v4DnsServers[VOICE_IPV4_ADDR_LEN*4]; /* opt 6, comma-separated */
char v4LogServerIp[VOICE_IPV4_ADDR_LEN]; /* opt 7 (syslog), if present */
char v4HostName[VOICE_STRMAX_128]; /* opt 12 */
char v4DomainName[VOICE_STRMAX_128]; /* opt 15 */
char v4ProvServer[VOICE_STRMAX_128]; /* PacketCable v4: Opt122 subopt 3 (IPv4/FQDN) */

/* DHCPv6 */
uint8_t isIpv6Up; /* at least one global IPv6 present */
char ipv6GlobalAddr[VOICE_IPV6_ADDR_LEN]; /* preferred global address */
char v6TftpServerIp[VOICE_IPV6_ADDR_LEN]; /* Opt17 subopt 32 (IPv6) */
char v6TftpFileName[VOICE_STRMAX_128]; /* Opt17 subopt 33 */
char v6SyslogServerIp[VOICE_IPV6_ADDR_LEN]; /* Opt17 subopt 34 (IPv6) */
char v6ProvServerIp[VOICE_STRMAX_128]; /* Opt17 subopt 2171:3 (IPv6/FQDN/IPv4 as text) */
char v6DnsServers[VOICE_IPV6_ADDR_LEN*4]; /* opt 23, comma-separated */
char v6DomainName[VOICE_STRMAX_128]; /* opt 24 (first decoded name) */
char v6ClientFqdn[VOICE_STRMAX_128]; /* opt 39 (decoded FQDN) */
} VoiceInterfaceInfoType;
#endif
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

Dead code that should be removed. Lines 299-328 contain a large block of commented-out structure definition that appears to be documentation or a reference. This should either be moved to proper documentation or removed entirely to avoid clutter and confusion.

Copilot uses AI. Check for mistakes.
Comment on lines 361 to 390
pthread_mutex_lock(&voiceDataProcessingMutex);
CcspTraceInfo(("%s:%d, DHCP Client Events Handler Thread started\n", __FUNCTION__, __LINE__));
DhcpEventData_t *pDhcpEvtData = (DhcpEventData_t *)pArg;
pthread_detach(pthread_self());

if (DHCP_IPv4 == pDhcpEvtData->dhcpVersion)
{
switch (pDhcpEvtData->dhcpMsgType)
{
case DHCP_CLIENT_STARTED:
case DHCP_CLIENT_STOPPED:
case DHCP_LEASE_RENEW:
case DHCP_LEASE_DEL:
case DHCP_LEASE_UPDATE:
{
processVoiceDhcpEvent((DhcpEventData_t *)pDhcpEvtData);
break;
}

default:
CcspTraceWarning(("%s: Unrecognized DHCPv4 message type %d\n", __FUNCTION__, pDhcpEvtData->dhcpMsgType));
break;
}
}
else
{
CcspTraceError(("%s: Unsupported DHCP version %d\n", __FUNCTION__, pDhcpEvtData->dhcpVersion));
}
free(pDhcpEvtData);
pthread_mutex_unlock(&voiceDataProcessingMutex);
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

Incorrect mutex usage pattern. The mutex is locked at the beginning of the thread (line 361), but if the thread is cancelled or exits unexpectedly before line 390, the mutex will remain locked indefinitely. The mutex lock should be placed after pthread_detach (line 364) and should use a more localized scope. Additionally, unlocking the mutex (line 390) immediately before pthread_exit (line 391) serves little purpose since the thread is terminating. Consider restructuring the mutex usage to protect only the critical sections where shared resources are accessed.

Copilot uses AI. Check for mistakes.

if (cVoiceSupportIfaceName[0] == '\0')
{
CcspTraceError(("%s:%d, VoiceSupport_IfaceName not set in syscfg, using default mta0\n", __FUNCTION__, __LINE__));
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

The error log message on line 251 uses CcspTraceError when it should use CcspTraceWarning or CcspTraceInfo. The message indicates a fallback to default behavior (using "mta0") rather than an actual error condition. This could confuse log analysis and alerting systems.

Suggested change
CcspTraceError(("%s:%d, VoiceSupport_IfaceName not set in syscfg, using default mta0\n", __FUNCTION__, __LINE__));
CcspTraceWarning(("%s:%d, VoiceSupport_IfaceName not set in syscfg, using default mta0\n", __FUNCTION__, __LINE__));

Copilot uses AI. Check for mistakes.
Comment on lines 1482 to 1486
*@breif This function get the wan interface name from sysevent
*@param pIfname - pointer to store the wan interface name
*@param iIfnameLen - length of the pointer
*@return ANSC_STATUS_SUCCESS on success else ANSC_STATUS_FAILURE
*/
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

Spelling error in the documentation comment. The word "breif" should be "brief".

Suggested change
*@breif This function get the wan interface name from sysevent
*@param pIfname - pointer to store the wan interface name
*@param iIfnameLen - length of the pointer
*@return ANSC_STATUS_SUCCESS on success else ANSC_STATUS_FAILURE
*/
*@brief This function get the wan interface name from sysevent
*@param pIfname - pointer to store the wan interface name
*@param iIfnameLen - length of the pointer
*@return ANSC_STATUS_SUCCESS on success else ANSC_STATUS_FAILURE
*/

Copilot uses AI. Check for mistakes.
free(pDhcpEvtData);
return;
}
usleep(10000); // Sleep for 10ms to allow thread to start
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

Potential thread creation issue with insufficient error recovery. If pthread_create fails on line 273, the allocated memory is freed correctly, but the calling code in dhcpClientEventsHandler continues execution without knowing that processing failed. Additionally, the usleep(10000) on line 279 is a fragile synchronization mechanism. Consider using proper thread synchronization primitives or redesigning to ensure the thread has properly started before continuing.

Suggested change
usleep(10000); // Sleep for 10ms to allow thread to start

Copilot uses AI. Check for mistakes.
Comment on lines 220 to 233
rbusValue_t rbusValue = rbusObject_GetValue(pRbusEvent->data, "Ifname");
snprintf(pDhcpEvtData->cIfaceName, sizeof(pDhcpEvtData->cIfaceName), "%s", rbusValue_GetString(rbusValue, NULL));
CcspTraceInfo(("%s: DHCP %s event for interface %s\n", __FUNCTION__,
(pDhcpEvtData->dhcpVersion == DHCP_IPv4) ? "IPv4" : "IPv6", pDhcpEvtData->cIfaceName));

rbusValue = rbusObject_GetValue(pRbusEvent->data, "MsgType");
pDhcpEvtData->dhcpMsgType = (DHCP_MESSAGE_TYPE)rbusValue_GetUInt32(rbusValue);
CcspTraceInfo(("%s: DHCP Message Type %d\n", __FUNCTION__, pDhcpEvtData->dhcpMsgType));

if (DHCP_LEASE_UPDATE == pDhcpEvtData->dhcpMsgType)
{
int iByteLen = 0;
rbusValue = rbusObject_GetValue(pRbusEvent->data, "LeaseInfo");
const uint8_t* pLeaseInfo = rbusValue_GetBytes(rbusValue, &iByteLen);
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

Missing null check for rbusObject_GetValue return value. The rbusValue returned by rbusObject_GetValue on lines 220, 225, and 232 may be NULL if the specified property doesn't exist in the event data. This would cause crashes when attempting to extract values. Add null checks before using these values.

Copilot uses AI. Check for mistakes.
}
CcspTraceInfo(("%s: Received event %s\n", __FUNCTION__, pRbusEvent->name));

pthread_t dhcpEventThreadId = -1;
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

Ambiguous variable naming. The variable "dhcpEventThreadId" is initialized to -1 (line 208), but pthread_t is typically an opaque type that shouldn't be initialized with integer values. The variable should either not be initialized or should be initialized with appropriate pthread types. Additionally, the thread ID is not used after thread creation, making the variable name misleading.

Suggested change
pthread_t dhcpEventThreadId = -1;
pthread_t dhcpEventThreadId;

Copilot uses AI. Check for mistakes.

typedef struct _DhcpEventData
{
char cIfaceName[32];
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

Inconsistent field naming in struct. The struct _DhcpEventData uses "cIfaceName" but it's referenced as "ifName" in the code comment on line 283 of cosa_voice_apis.c. While "cIfaceName" follows Hungarian notation (c prefix for char array), this should be consistently named across the codebase. Consider using just "ifaceName" or "interfaceName" for clarity.

Copilot uses AI. Check for mistakes.
Reason for change:Subscribing for DHCP events via R-BUS
Test Procedure: verify the DHCP message is received or not
Risks: High
Priority: P1
Reason for change:Initializing the voice
Test Procedure: verify the voice is initialized or not
Risks: High
Priority: P1
Reason for change:Extractign the received data from the provider
Test Procedure: verify the voice is initialized or not
Risks: High
Priority: P1
Copilot AI review requested due to automatic review settings February 4, 2026 20:18
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 23 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

/* Default all protocol to UDP except TCP. Do not support "TCP or UDP" option. */
if (!strcmp("TCP", pFirewallRule->protocol))
{
strcpy(protocol, "TCP");
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The function cbSetFirewallRule uses strcpy on line 849 to copy into a stack buffer without bounds checking. While the source "TCP" is a string literal and safe in this case, using strcpy is generally discouraged. Consider using strncpy or safer string handling functions to maintain consistency with security best practices throughout the codebase.

Suggested change
strcpy(protocol, "TCP");
strcpy_s(protocol, sizeof(protocol), "TCP");

Copilot uses AI. Check for mistakes.
Comment on lines 841 to 861
static uint8_t cbSetFirewallRule(VoiceFirewallRuleType *pFirewallRule)
{
char command[1000] = { 0 };
char protocol[10] = "UDP";

/* Default all protocol to UDP except TCP. Do not support "TCP or UDP" option. */
if (!strcmp("TCP", pFirewallRule->protocol))
{
strcpy(protocol, "TCP");
}

AnscTraceInfo(("%s: enable=%d, ifName=%s, protocol=%s, destPort=%u\n",
__FUNCTION__, pFirewallRule->enable,
pFirewallRule->ifName,
protocol,
pFirewallRule->destinationPort));
if (pFirewallRule->enable)
{
snprintf(command, sizeof(command), "-A INPUT -p %s -i %s --dport %u -j ACCEPT",
protocol, pFirewallRule->ifName, pFirewallRule->destinationPort);
}
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The snprintf call constructs an iptables command using user-controlled data (protocol, ifName, destinationPort from pFirewallRule) without input validation. While these values come from the voice HAL, they could potentially contain shell metacharacters if compromised. The command is then passed to setSysevent which eventually executes it via sysevent. Validate that ifName contains only alphanumeric characters and valid interface name characters, protocol is either "TCP" or "UDP", and destinationPort is a valid port number before constructing the command.

Suggested change
static uint8_t cbSetFirewallRule(VoiceFirewallRuleType *pFirewallRule)
{
char command[1000] = { 0 };
char protocol[10] = "UDP";
/* Default all protocol to UDP except TCP. Do not support "TCP or UDP" option. */
if (!strcmp("TCP", pFirewallRule->protocol))
{
strcpy(protocol, "TCP");
}
AnscTraceInfo(("%s: enable=%d, ifName=%s, protocol=%s, destPort=%u\n",
__FUNCTION__, pFirewallRule->enable,
pFirewallRule->ifName,
protocol,
pFirewallRule->destinationPort));
if (pFirewallRule->enable)
{
snprintf(command, sizeof(command), "-A INPUT -p %s -i %s --dport %u -j ACCEPT",
protocol, pFirewallRule->ifName, pFirewallRule->destinationPort);
}
static int isValidInterfaceName(const char *ifName)
{
size_t i;
if (ifName == NULL || ifName[0] == '\0')
{
return 0;
}
for (i = 0; ifName[i] != '\0'; ++i)
{
unsigned char c = (unsigned char)ifName[i];
if (!isalnum(c) && c != '_' && c != '.' && c != '-' && c != ':')
{
return 0;
}
}
return 1;
}
static int isValidProtocol(const char *protocolIn, char *protocolOut, size_t protocolOutLen)
{
if (protocolOut == NULL || protocolOutLen < 4)
{
return 0;
}
/* Only allow TCP or UDP explicitly. Default to UDP only if input is exactly "UDP". */
if (protocolIn != NULL)
{
if (strcmp(protocolIn, "TCP") == 0)
{
strcpy(protocolOut, "TCP");
return 1;
}
else if (strcmp(protocolIn, "UDP") == 0)
{
strcpy(protocolOut, "UDP");
return 1;
}
}
return 0;
}
static int isValidPort(uint32_t port)
{
/* Valid TCP/UDP ports are in the range 1-65535. */
if (port == 0 || port > 65535)
{
return 0;
}
return 1;
}
static uint8_t cbSetFirewallRule(VoiceFirewallRuleType *pFirewallRule)
{
char command[1000] = { 0 };
char protocol[10] = "UDP";
if (pFirewallRule == NULL)
{
AnscTraceError(("%s: pFirewallRule is NULL\n", __FUNCTION__));
return 0;
}
/* Validate inputs before constructing firewall rule when enabling. */
if (pFirewallRule->enable)
{
if (!isValidInterfaceName(pFirewallRule->ifName))
{
AnscTraceError(("%s: Invalid interface name: %s\n",
__FUNCTION__,
(pFirewallRule->ifName != NULL) ? pFirewallRule->ifName : "(null)"));
return 0;
}
if (!isValidProtocol(pFirewallRule->protocol, protocol, sizeof(protocol)))
{
AnscTraceError(("%s: Invalid protocol: %s\n",
__FUNCTION__,
(pFirewallRule->protocol != NULL) ? pFirewallRule->protocol : "(null)"));
return 0;
}
if (!isValidPort(pFirewallRule->destinationPort))
{
AnscTraceError(("%s: Invalid destination port: %u\n",
__FUNCTION__, pFirewallRule->destinationPort));
return 0;
}
}
AnscTraceInfo(("%s: enable=%d, ifName=%s, protocol=%s, destPort=%u\n",
__FUNCTION__, pFirewallRule->enable,
(pFirewallRule->ifName != NULL) ? pFirewallRule->ifName : "(null)",
protocol,
pFirewallRule->destinationPort));
if (pFirewallRule->enable)
{
snprintf(command, sizeof(command),
"-A INPUT -p %s -i %s --dport %u -j ACCEPT",
protocol, pFirewallRule->ifName, pFirewallRule->destinationPort);
}

Copilot uses AI. Check for mistakes.
{
CcspTraceInfo(("%s: Processing DHCPv4 LeaseInfo of size %d\n", __FUNCTION__, iByteLen));
CcspTraceInfo(("%s:%d, DHCP_MGR_IPV4_MSG size: %ld\n", __FUNCTION__, __LINE__, sizeof(DHCP_MGR_IPV4_MSG)));
if (sizeof(DHCP_MGR_IPV4_MSG) == iByteLen)
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The size check on line 268 verifies that the received lease info size matches sizeof(DHCP_MGR_IPV4_MSG) using equality. While this ensures the structures match exactly, it's fragile to structure padding and version changes. If the structure size changes slightly (due to compiler differences, padding, or version updates), valid data might be rejected. Consider using a minimum size check instead of exact equality, or add version/magic number fields to the structure for more robust validation.

Copilot uses AI. Check for mistakes.
Comment on lines 2642 to 2731
<?ifdef FEATURE_SUPPORT_VOICE_MTA?>
<object><name>Services</name><objectType>object</objectType>
<objects><object><name>BrcmVoiceService</name><objectType>object</objectType>

<functions>
<func_SetParamStringValue>BrcmVoiceService_NotifyIfIp_SetParamStringValue</func_SetParamStringValue>
</functions>

<parameters>
<parameter>
<name>X_BROADCOM_COM_NotifyIfIp</name>
<type>string(128)</type><syntax>string</syntax><writable>true</writable>
</parameter>
</parameters>

<objects><object><name>1</name><objectType>object</objectType>

<functions>
<func_GetParamStringValue>BrcmVoiceService_GetParamStringValue</func_GetParamStringValue>
<func_SetParamStringValue>BrcmVoiceService_SetParamStringValue</func_SetParamStringValue>
</functions>

<parameters>
<parameter>
<name>X_BROADCOM_COM_BoundIfName</name>
<type>string(32)</type><syntax>string</syntax><writable>true</writable>
</parameter>
<parameter>
<name>X_BROADCOM_COM_ModuleLogLevels</name>
<type>string(128)</type><syntax>string</syntax><writable>true</writable>
</parameter>
</parameters>

<objects><object><name>SIP</name><objectType>object</objectType>

<objects>
<object><name>Network</name><objectType>object</objectType>
<objects><object><name>1</name><objectType>object</objectType>

<functions>
<func_GetParamStringValue>BrcmVoiceNetwork_GetParamStringValue</func_GetParamStringValue>
<func_SetParamStringValue>BrcmVoiceNetwork_SetParamStringValue</func_SetParamStringValue>
</functions>

<parameters>
<parameter>
<name>ProxyServer</name>
<type>string(128)</type><syntax>string</syntax><writable>true</writable>
</parameter>
<parameter>
<name>RegistrarServer</name>
<type>string(128)</type><syntax>string</syntax><writable>true</writable>
</parameter>
</parameters>

</object></objects>
</object>

<object><name>Client</name><objectType>object</objectType>
<objects><object><name>1</name><objectType>object</objectType>

<functions>
<func_GetParamStringValue>BrcmVoiceClient_GetParamStringValue</func_GetParamStringValue>
<func_SetParamStringValue>BrcmVoiceClient_SetParamStringValue</func_SetParamStringValue>
</functions>

<parameters>
<parameter>
<name>RegisterURI</name>
<type>string(128)</type><syntax>string</syntax><writable>true</writable>
</parameter>
<parameter>
<name>AuthUserName</name>
<type>string(128)</type><syntax>string</syntax><writable>true</writable>
</parameter>
<parameter>
<name>AuthPassword</name>
<type>string(128)</type><syntax>string</syntax><writable>true</writable>
</parameter>
</parameters>

</object></objects>
</object>
</objects>

</object></objects>
</object></objects>
</object></objects>
</object>
<?endif?>
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The XML configuration introduces new data model objects under Services.BrcmVoiceService with various string parameters. However, there's no input validation specified in the XML or visible in the corresponding DML functions (BrcmVoiceService_SetParamStringValue, BrcmVoiceNetwork_SetParamStringValue, BrcmVoiceClient_SetParamStringValue) that validates the input before passing it to bcm_generic_setParameterValues. Consider adding length checks and format validation for parameters like RegisterURI, ProxyServer, RegistrarServer, etc., to prevent injection attacks or malformed data from being stored.

Copilot uses AI. Check for mistakes.
free(pDhcpEvtData);
return;
}
usleep(10000); // Sleep for 10ms to allow thread to start
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The usleep(10000) call after pthread_create is used to "allow thread to start". This is a race condition fix attempt that is fragile and not guaranteed to work. Instead of sleeping, consider using proper synchronization mechanisms (e.g., condition variables, or checking return values) to ensure the thread has properly started if that's actually necessary. In most cases, pthread_create returning 0 is sufficient indication that the thread was created successfully, and no additional synchronization is needed.

Suggested change
usleep(10000); // Sleep for 10ms to allow thread to start

Copilot uses AI. Check for mistakes.
Comment on lines 240 to 241
rbusValue_t rbusValue = rbusObject_GetValue(dataObj, "IfName");
const char *pIfaceName = rbusValue_GetString(rbusValue, NULL);
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

In the dhcpClientEventsHandler, when retrieving the IfName from the RBUS event (lines 240-242), rbusValue_GetString is called without checking if rbusValue is NULL. If rbusObject_GetValue returns NULL (meaning the "IfName" property doesn't exist), the subsequent rbusValue_GetString call will dereference a NULL pointer. Add a NULL check for rbusValue before calling rbusValue_GetString.

Copilot uses AI. Check for mistakes.
Comment on lines 252 to 253
rbusValue = rbusObject_GetValue(dataObj, "MsgType");
pDhcpEvtData->dhcpMsgType = (DHCP_MESSAGE_TYPE)rbusValue_GetUInt32(rbusValue);
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

Similar to the IfName retrieval, when getting "MsgType" on lines 252-253, rbusValue is not checked for NULL before calling rbusValue_GetUInt32. Add NULL checks for all rbusObject_GetValue calls before using the returned rbusValue.

Copilot uses AI. Check for mistakes.
.userData = NULL,
.handle = NULL,
.asyncHandler = NULL,
.publishOnSubscribe = true
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The publishOnSubscribe flag is set to true in the RBUS event subscription on line 360. This means when subscribing, the DHCP manager will immediately publish the current state. The handler checks for and unwraps "initialValue" (lines 233-239), which is good. However, if the initial event contains no valid LeaseInfo (e.g., DHCP client not yet started), the handler will free pDhcpEvtData and return early (lines 309-311, 316-318). This is correct behavior, but consider logging at Info level rather than Error level for these cases, since receiving an initial event without lease info is expected when publishOnSubscribe is true and DHCP hasn't completed yet.

Copilot uses AI. Check for mistakes.
Comment on lines 1361 to 1362
CcspTraceWarning(("%s:%d, current_wan_state up, Initializing MTA Inteface \n",__FUNCTION__,__LINE__));
startVoiceFeature();
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The function startVoiceFeature is called in two different locations (lines 1314 and 1362) when current_wan_state is up. This could lead to duplicate MTA interface creation attempts if both code paths are executed. The static boolean isVoiceFeatureStarted provides protection, but calling the same function from multiple locations indicates unclear control flow. Consider consolidating the initialization logic to avoid redundant calls.

Suggested change
CcspTraceWarning(("%s:%d, current_wan_state up, Initializing MTA Inteface \n",__FUNCTION__,__LINE__));
startVoiceFeature();
CcspTraceWarning(("%s:%d, current_wan_state up notification received\n", __FUNCTION__, __LINE__));

Copilot uses AI. Check for mistakes.
AnscTraceInfo(("%s: Calling sysevent command: %s\n", __FUNCTION__, pCommand));
if (ui8Enable)
{
if (NULL == pCommand || '\0' == pCommand[0] || strlen(pCommand) <= 0)
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The condition on line 825 checks three redundant conditions: NULL == pCommand, '\0' == pCommand[0], and strlen(pCommand) <= 0. The first check prevents NULL pointer dereference. The second check (pCommand[0] == '\0') is sufficient to check for empty string. The third check strlen(pCommand) <= 0 is redundant because strlen cannot return negative values, and checking for 0 is the same as pCommand[0] == '\0'. Simplify to: if (NULL == pCommand || pCommand[0] == '\0')

Suggested change
if (NULL == pCommand || '\0' == pCommand[0] || strlen(pCommand) <= 0)
if (NULL == pCommand || '\0' == pCommand[0])

Copilot uses AI. Check for mistakes.
Reason for change:filling the hal structure with provisioning server details
Test Procedure: verify the voice is initialized or not
Risks: High
Priority: P1
Reason for change:Extracting the received data from the provider
Test Procedure: verify the voice is initialized or not
Risks: High
Priority: P1
Copilot AI review requested due to automatic review settings February 7, 2026 03:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 15 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 128 to 134
return;
}
else
{
CcspTraceInfo(("%s: PSM_Get_Record_Value2 successful for param %s with value %s\n", __FUNCTION__, DHCPv4_VOICE_SUPPORT_PARAM,
pParamValue));
snprintf(cBaseParam, sizeof(cBaseParam), "%s",pParamValue);
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

If PSM_Get_Record_Value2 fails, cBaseParam remains empty, but subsequent code still builds RBUS parameter names from it (e.g., ".Interface", ".Events"), which will cause RBUS set/subscribe to target invalid paths. Consider setting a safe default or returning an error that prevents later RBUS operations when cBaseParam is unset.

Suggested change
return;
}
else
{
CcspTraceInfo(("%s: PSM_Get_Record_Value2 successful for param %s with value %s\n", __FUNCTION__, DHCPv4_VOICE_SUPPORT_PARAM,
pParamValue));
snprintf(cBaseParam, sizeof(cBaseParam), "%s",pParamValue);
/* Set a safe default base parameter to avoid constructing invalid RBUS paths later. */
snprintf(cBaseParam, sizeof(cBaseParam), "%s", DHCP_MGR_DHCPv4_TABLE);
return;
}
else
{
CcspTraceInfo(("%s: PSM_Get_Record_Value2 successful for param %s with value %s\n", __FUNCTION__, DHCPv4_VOICE_SUPPORT_PARAM,
pParamValue));
snprintf(cBaseParam, sizeof(cBaseParam), "%s", pParamValue);

Copilot uses AI. Check for mistakes.
Comment on lines +556 to +560
case DHCP_CLIENT_STARTED:
case DHCP_CLIENT_STOPPED:
case DHCP_LEASE_RENEW:
case DHCP_LEASE_DEL:
case DHCP_LEASE_UPDATE:
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

DHCP_CLIENT_STOPPED / DHCP_LEASE_DEL represent loss of lease/client down, but they are currently grouped with renew/update and will be processed as if the interface is up. Handle these message types separately (cleanup routes/rules and notify down) instead of treating them like lease updates.

Copilot uses AI. Check for mistakes.
Comment on lines +473 to +477
const char *pHexOption122Data = pDhcpEvtData->leaseInfo.dhcpV4Msg.cOption122;
uint16_t iOption122Len = strlen(pHexOption122Data) / 2;
uint8_t ui8Option122Data[iOption122Len];
memset(ui8Option122Data, 0, sizeof(ui8Option122Data));
hexStringToByteArray(pHexOption122Data, ui8Option122Data, iOption122Len);
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

initializeVoiceSupport derives iOption122Len from strlen(cOption122)/2 and then declares a VLA uint8_t ui8Option122Data[iOption122Len];. If cOption122 is empty, odd-length, or unexpectedly large, this can result in a zero-sized/huge VLA and undefined behavior or stack exhaustion. Add validation (non-empty, even hex length, reasonable max) and avoid VLAs by using a fixed-size buffer or heap allocation with bounds checks.

Copilot uses AI. Check for mistakes.
Comment on lines 684 to 690
if (len >= (int)(sizeof(in6Addr.s6_addr) + 4)) // Account for 2 byte tag and length
{
char tmpBuff[MAX_STR] = {0};

memcpy(&in6Addr.s6_addr, tmpBuff, sizeof(in6Addr.s6_addr));
inet_ntop(AF_INET6, &in6Addr, pIfInfo->v6DnsServers, sizeof(pIfInfo->v6DnsServers));
AnscTraceVerbose(("option 23 v6DnsServers = [%s]\n", pIfInfo->v6DnsServers));
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

This memcpy populates in6Addr from tmpBuff, but tmpBuff is never filled. As a result, v6DnsServers will be based on zero/garbage instead of option-23 data. Copy from the decrypted option-23 buffer (or parse it properly) before calling inet_ntop.

Suggested change
if (len >= (int)(sizeof(in6Addr.s6_addr) + 4)) // Account for 2 byte tag and length
{
char tmpBuff[MAX_STR] = {0};
memcpy(&in6Addr.s6_addr, tmpBuff, sizeof(in6Addr.s6_addr));
inet_ntop(AF_INET6, &in6Addr, pIfInfo->v6DnsServers, sizeof(pIfInfo->v6DnsServers));
AnscTraceVerbose(("option 23 v6DnsServers = [%s]\n", pIfInfo->v6DnsServers));
if (len >= (int)(sizeof(uint16_t) * 2 + sizeof(in6Addr.s6_addr))) /* option code + length + at least one IPv6 address */
{
/* The option format is: uint16_t code, uint16_t length, followed by data (one or more IPv6 addresses). */
subLen = ntohs(*(uint16_t *)(buffer + sizeof(uint16_t))); /* length of the option data */
if (subLen >= (int)sizeof(in6Addr.s6_addr))
{
/* Copy the first IPv6 address from the option payload */
memcpy(in6Addr.s6_addr, buffer + (sizeof(uint16_t) * 2), sizeof(in6Addr.s6_addr));
inet_ntop(AF_INET6, &in6Addr, pIfInfo->v6DnsServers, sizeof(pIfInfo->v6DnsServers));
AnscTraceVerbose(("option 23 v6DnsServers = [%s]\n", pIfInfo->v6DnsServers));
}

Copilot uses AI. Check for mistakes.
Comment on lines 145 to 149
subLen = buf[i];
if (0 == subLen)
{
fqdn[i - 1] = '\0';
}
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

When subLen is 0, this writes fqdn[i-1]. If i==0 (e.g., empty/zero-length input), this becomes an out-of-bounds write. Add guards for empty input and only write fqdn[i-1] when i>0, while still ensuring the output is NUL-terminated.

Copilot uses AI. Check for mistakes.
};

pthread_t eventSubscriptionThreadId = -1;
if (pthread_create(&eventSubscriptionThreadId, NULL, (void *)eventSubscriptionThread, (void *)&rbusEventSubscription) != 0)
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

pthread_create is called with (void *)eventSubscriptionThread as the start routine. This is an incompatible cast (function pointer -> object pointer) and can fail compilation or invoke UB. Pass eventSubscriptionThread directly (type void* (*)(void*)) without casting to void*.

Suggested change
if (pthread_create(&eventSubscriptionThreadId, NULL, (void *)eventSubscriptionThread, (void *)&rbusEventSubscription) != 0)
if (pthread_create(&eventSubscriptionThreadId, NULL, eventSubscriptionThread, (void *)&rbusEventSubscription) != 0)

Copilot uses AI. Check for mistakes.
Comment on lines 557 to 566
case DHCP_CLIENT_STOPPED:
case DHCP_LEASE_RENEW:
case DHCP_LEASE_DEL:
case DHCP_LEASE_UPDATE:
case DHCP_CLIENT_FAILED:
{
processVoiceDhcpEvent((DhcpEventData_t *)pDhcpEvtData);
break;
}

Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

processVoiceDhcpEvent() adds routes/rules and populates VoiceInterfaceInfoType with isIpv4Up = 1 for every message type in this block. For failure/stop/delete events this will push incorrect state and leave stale routing policy. Consider branching by dhcpMsgType so only lease-acquired/renewed paths add routes, and teardown paths remove them.

Suggested change
case DHCP_CLIENT_STOPPED:
case DHCP_LEASE_RENEW:
case DHCP_LEASE_DEL:
case DHCP_LEASE_UPDATE:
case DHCP_CLIENT_FAILED:
{
processVoiceDhcpEvent((DhcpEventData_t *)pDhcpEvtData);
break;
}
case DHCP_LEASE_RENEW:
case DHCP_LEASE_UPDATE:
{
/* Lease-acquired/renew/update events: process to add/update routes and state */
processVoiceDhcpEvent((DhcpEventData_t *)pDhcpEvtData);
break;
}
case DHCP_CLIENT_STOPPED:
case DHCP_LEASE_DEL:
case DHCP_CLIENT_FAILED:
{
/* Teardown/failure events: avoid calling processVoiceDhcpEvent() to prevent
* incorrectly marking IPv4 as up or adding routes. Any teardown-specific
* handling should be implemented in a dedicated path.
*/
CcspTraceInfo(("%s: DHCPv4 teardown/failure event %d received for interface %s\n",
__FUNCTION__, pDhcpEvtData->dhcpMsgType, pDhcpEvtData->ifName));
break;
}

Copilot uses AI. Check for mistakes.
Comment on lines 198 to 203
/* Read tag */
subCode = ntohs(*((uint16_t *)(buffPtr)));
buffPtr += sizeof(uint16_t);

/* Read length */
subLen = ntohs(*((uint16_t *)(buffPtr)));
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

Casting buffPtr to uint16_t* can cause unaligned memory access on some platforms. Read the 16-bit fields with memcpy (or byte-wise) before applying ntohs to avoid UB/crashes.

Suggested change
/* Read tag */
subCode = ntohs(*((uint16_t *)(buffPtr)));
buffPtr += sizeof(uint16_t);
/* Read length */
subLen = ntohs(*((uint16_t *)(buffPtr)));
uint16_t tmp16;
/* Read tag */
memcpy(&tmp16, buffPtr, sizeof(tmp16));
subCode = ntohs(tmp16);
buffPtr += sizeof(uint16_t);
/* Read length */
memcpy(&tmp16, buffPtr, sizeof(tmp16));
subLen = ntohs(tmp16);

Copilot uses AI. Check for mistakes.
Comment on lines 1422 to 1425
#if defined(SCXF10)
getIfaceIndexInfo();
initRbusHandle();
#endif
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

getIfaceIndexInfo() / initRbusHandle() are called when SCXF10 is defined, but their implementations are only compiled when the Automake conditional VOICE_SUPPORT_ENABLED adds cosa_rbus_apis.c to the build. If SCXF10 can be enabled without --enable-voice_support, this will cause unresolved symbols at link time. Consider guarding these calls with the same feature macro used for compilation, or always compile the RBUS/voice sources when SCXF10 is enabled.

Copilot uses AI. Check for mistakes.
Comment on lines 427 to 433
pthread_t eventSubscriptionThreadId = -1;
if (pthread_create(&eventSubscriptionThreadId, NULL, (void *)eventSubscriptionThread, (void *)&rbusEventSubscription) != 0)
{
CcspTraceError(("%s: Failed to create event subscription thread\n", __FUNCTION__));
return;
}
pthread_detach(eventSubscriptionThreadId);
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

subscribeDhcpClientEvents() passes the address of a stack-allocated rbusEventSubscription_t into a detached thread. After this function returns, the thread will dereference invalid memory (use-after-scope). Allocate the subscription struct with a lifetime that outlives the thread (heap/static), or subscribe synchronously without spawning a thread.

Suggested change
pthread_t eventSubscriptionThreadId = -1;
if (pthread_create(&eventSubscriptionThreadId, NULL, (void *)eventSubscriptionThread, (void *)&rbusEventSubscription) != 0)
{
CcspTraceError(("%s: Failed to create event subscription thread\n", __FUNCTION__));
return;
}
pthread_detach(eventSubscriptionThreadId);
CcspTraceInfo(("%s:%d, Subscribing to event %s synchronously\n", __FUNCTION__, __LINE__, rbusEventSubscription.eventName));
rbusError_t rbusRet = rbusEvent_SubscribeEx(voiceRbusHandle, &rbusEventSubscription, 1 /* Number of subscriptions */, 5 /* retry interval in seconds */);
if (rbusRet != RBUS_ERROR_SUCCESS)
{
CcspTraceError(("%s: rbus_event_subscribe failed for event %s with error code %d\n", __FUNCTION__, rbusEventSubscription.eventName, rbusRet));
}
else
{
CcspTraceInfo(("%s: rbus_event_subscribe successful for event %s\n", __FUNCTION__, rbusEventSubscription.eventName));
}

Copilot uses AI. Check for mistakes.
Reason for change:Setting the ifname in bcm if not set
Test Procedure: verify the voice is initialized or not
Risks: High
Priority: P1
*/
void startVoiceFeature(void)
{
static bool isVoiceFeatureStarted = false;
Copy link
Author

Choose a reason for hiding this comment

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

remove this check

{
CcspTraceInfo(("%s: rbus_event_subscribe successful for event %s\n", __FUNCTION__, rbusEventSubscription.eventName));
}
return NULL;
Copy link
Author

Choose a reason for hiding this comment

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

add a pthread exit

Copilot AI review requested due to automatic review settings February 13, 2026 00:28
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 31 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +538 to +556
switch (pDhcpEvtData->dhcpMsgType)
{
case DHCP_CLIENT_STARTED:
case DHCP_CLIENT_STOPPED:
case DHCP_LEASE_RENEW:
case DHCP_LEASE_DEL:
case DHCP_LEASE_UPDATE:
case DHCP_CLIENT_FAILED:
{
pthread_mutex_lock(&voiceDataProcessingMutex);
processVoiceDhcpEvent((DhcpEventData_t *)pDhcpEvtData);
pthread_mutex_unlock(&voiceDataProcessingMutex);
break;
}

default:
CcspTraceWarning(("%s: Unrecognized DHCPv4 message type %d\n", __FUNCTION__, pDhcpEvtData->dhcpMsgType));
break;
}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

The dhcpClientEventsHandler processes all message types (DHCP_CLIENT_STARTED, STOPPED, LEASE_RENEW, LEASE_DEL, LEASE_UPDATE, CLIENT_FAILED) identically by calling processVoiceDhcpEvent. However, processVoiceDhcpEvent always adds IP routes and initializes voice support. For events like LEASE_DEL or CLIENT_STOPPED, this logic doesn't make sense - these should likely tear down routes and deinitialize, not set them up. Consider implementing different handling logic for different event types.

Copilot uses AI. Check for mistakes.
Comment on lines +888 to +899
static char voiceInterface[32] = { 0 };

static uint8_t cbSubsIfInfo(char *pIntfName, uint8_t enable)
{
if (enable)
{
/* Save voice interface selection */
strncpy(voiceInterface, pIntfName, sizeof(voiceInterface));
}

return 1;
}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Static global variable voiceInterface is accessed by callback functions without synchronization. If callbacks are invoked from different threads, this could lead to race conditions. Consider adding mutex protection or documenting thread-safety requirements.

Copilot uses AI. Check for mistakes.
Comment on lines +432 to +453
strncpy(sVoiceInterfaceInfoType.ipv4Addr, pDhcpEvtData->leaseInfo.dhcpV4Msg.address, sizeof(sVoiceInterfaceInfoType.ipv4Addr)-1);
strncpy(sVoiceInterfaceInfoType.v4NextServerIp, pDhcpEvtData->leaseInfo.dhcpV4Msg.cTftpServer, sizeof(sVoiceInterfaceInfoType.v4NextServerIp)-1);
strncpy(sVoiceInterfaceInfoType.v4BootFileName, pDhcpEvtData->leaseInfo.dhcpV4Msg.cOption67, sizeof(sVoiceInterfaceInfoType.v4BootFileName)-1);

char cTmpDnsServers[VOICE_IPV4_ADDR_LEN*4] = {0};
int iBufSize = sizeof(cTmpDnsServers);
int iLen = 0;
strncpy(cTmpDnsServers, pDhcpEvtData->leaseInfo.dhcpV4Msg.dnsServer, iBufSize-1);
cTmpDnsServers[iBufSize -1] = '\0';
iLen = strlen(cTmpDnsServers);
if (iLen < (iBufSize -1) && strlen(pDhcpEvtData->leaseInfo.dhcpV4Msg.dnsServer1) > 0)
{
if (iLen > 0)
{
strncat(cTmpDnsServers, ",", iBufSize - strlen(cTmpDnsServers) -1);
}
strncat(cTmpDnsServers, pDhcpEvtData->leaseInfo.dhcpV4Msg.dnsServer1, iBufSize - strlen(cTmpDnsServers) -1);
}

strncpy(sVoiceInterfaceInfoType.v4DnsServers, cTmpDnsServers, sizeof(sVoiceInterfaceInfoType.v4DnsServers)-1);
strncpy(sVoiceInterfaceInfoType.v4HostName, pDhcpEvtData->leaseInfo.dhcpV4Msg.cHostName, sizeof(sVoiceInterfaceInfoType.v4HostName)-1);
strncpy(sVoiceInterfaceInfoType.v4DomainName, pDhcpEvtData->leaseInfo.dhcpV4Msg.cDomainName, sizeof(sVoiceInterfaceInfoType.v4DomainName)-1);
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

The strncpy calls do not guarantee null-termination if the source string equals or exceeds the destination buffer size. While the '-1' in the size parameter helps, the subsequent array access patterns could still be problematic. Use snprintf or ensure explicit null-termination after each strncpy call.

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

//Commend out the broadcom patch changes for now, will be requried to test basic voice functionality supported by broadcom.
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Typo in comment: "Commend" should be "Comment".

Copilot uses AI. Check for mistakes.
);
int CosaDmlTR104DataSet(char* pString,int bootup);

//Commend out the broadcom patch changes for now, will be requried to test basic voice functionality supported by broadcom.
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Typo in comment: "Commend" should be "Comment".

Suggested change
//Commend out the broadcom patch changes for now, will be requried to test basic voice functionality supported by broadcom.
//Comment out the broadcom patch changes for now, will be requried to test basic voice functionality supported by broadcom.

Copilot uses AI. Check for mistakes.
Comment on lines +322 to +331
snprintf(cParamName, sizeof(cParamName), "ip route add %s dev %s", pDhcpEvtData->leaseInfo.dhcpV4Msg.address, pDhcpEvtData->cIfaceName);
system(cParamName);
snprintf(cParamName, sizeof(cParamName), "ip route add %s via %s dev %s", pDhcpEvtData->leaseInfo.dhcpV4Msg.cTftpServer, pDhcpEvtData->leaseInfo.dhcpV4Msg.gateway, pDhcpEvtData->cIfaceName);
system(cParamName);
snprintf(cParamName, sizeof(cParamName), "ip rule add from %s table 21", pDhcpEvtData->leaseInfo.dhcpV4Msg.address);
system(cParamName);
snprintf(cParamName, sizeof(cParamName), "ip route add %s dev %s table 21", cNetworkAddrWithCidr, pDhcpEvtData->cIfaceName);
system(cParamName);
snprintf(cParamName, sizeof(cParamName), "ip route add default via %s dev %s table 21", pDhcpEvtData->leaseInfo.dhcpV4Msg.gateway, pDhcpEvtData->cIfaceName);
system(cParamName);
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Using system() to execute shell commands creates a command injection vulnerability. The variables from pDhcpEvtData (including addresses and gateway from DHCP responses) are used directly in command strings. An attacker controlling DHCP responses could inject malicious commands. Use safer alternatives like direct netlink API calls or properly escape all inputs.

Copilot uses AI. Check for mistakes.
Comment on lines +198 to +199
if (cWanIfname[0] == '\0')
snprintf(cWanIfname, sizeof(cWanIfname), "erouter0");
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Missing error handling: If getWanIfaceName fails (returns ANSC_STATUS_FAILURE), cWanIfname will still contain an empty string and the fallback to "erouter0" will be used. However, there's no log message indicating this fallback is happening. Consider adding a trace message when the fallback occurs to aid debugging.

Suggested change
if (cWanIfname[0] == '\0')
snprintf(cWanIfname, sizeof(cWanIfname), "erouter0");
if (cWanIfname[0] == '\0')
{
CcspTraceInfo(("%s:%d, getWanIfaceName returned empty, falling back to default WAN interface 'erouter0'\n", __FUNCTION__, __LINE__));
snprintf(cWanIfname, sizeof(cWanIfname), "erouter0");
}

Copilot uses AI. Check for mistakes.
Comment on lines +354 to +355
for (int iIndex = 0; iIndex < iByteArrayLen && (iIndex * 2 + 1) < iHexStringLen; iIndex++)
{
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Missing bounds check: The integer arithmetic (iIndex * 2 + 1) at line 354 could potentially overflow if iByteArrayLen is very large. While unlikely in practice for DHCP options, consider adding a bounds check to prevent potential issues.

Suggested change
for (int iIndex = 0; iIndex < iByteArrayLen && (iIndex * 2 + 1) < iHexStringLen; iIndex++)
{
int maxBytesFromHex = iHexStringLen / 2;
if (maxBytesFromHex > iByteArrayLen)
{
maxBytesFromHex = iByteArrayLen;
}
for (int iIndex = 0; iIndex < maxBytesFromHex; iIndex++)
{

Copilot uses AI. Check for mistakes.
Comment on lines +231 to +278
void startVoiceFeature(void)
{

char cVoiceSupportEnabled[8] = {0};
char cVoiceSupportMode[32] = {0};
char cVoiceSupportIfaceName[32] = {0};


syscfg_get(NULL, "VoiceSupport_IfaceName",cVoiceSupportIfaceName, sizeof(cVoiceSupportIfaceName));
syscfg_get(NULL, "VoiceSupport_Mode",cVoiceSupportMode, sizeof(cVoiceSupportMode));
syscfg_get(NULL, "VoiceSupport_Enabled", cVoiceSupportEnabled, sizeof(cVoiceSupportEnabled));

if (cVoiceSupportEnabled[0] == '\0' || strcmp(cVoiceSupportEnabled, "true") != 0)
{
CcspTraceError(("%s:%d, VoiceSupport_Enabled is false or not set, skipping MTA interface creation\n", __FUNCTION__, __LINE__));
return;
}

if (cVoiceSupportIfaceName[0] == '\0')
{
CcspTraceWarning(("%s:%d, VoiceSupport_IfaceName not set in syscfg, using default mta0\n", __FUNCTION__, __LINE__));
snprintf(cVoiceSupportIfaceName, sizeof(cVoiceSupportIfaceName), "mta0");
}

if (cVoiceSupportMode[0] == '\0')
{
CcspTraceWarning(("%s:%d, VoiceSupport_Mode not set in syscfg, using default Dual_Stack\n", __FUNCTION__, __LINE__));
snprintf(cVoiceSupportMode, sizeof(cVoiceSupportMode), VOICE_SUPPORT_MODE_DUAL_STACK);
}

if (createMtaInterface(cVoiceSupportIfaceName) == 0)
{
CcspTraceInfo(("%s:%d, MTA interface created successfully\n", __FUNCTION__, __LINE__));
} else {
CcspTraceError(("%s:%d, Failed to create MTA interface\n", __FUNCTION__, __LINE__));
return;
}
subscribeDhcpClientEvents();

if (0 == strcmp(cVoiceSupportMode, VOICE_SUPPORT_MODE_IPV4_ONLY) || 0 == strcmp(cVoiceSupportMode, VOICE_SUPPORT_MODE_DUAL_STACK))
{
CcspTraceInfo(("%s:%d, Starting udhcpc on MTA interface\n", __FUNCTION__, __LINE__));
if (false == isIfaceHasIp(cVoiceSupportIfaceName))
enableDhcpv4ForMta(cVoiceSupportIfaceName);
} else {
CcspTraceInfo(("%s:%d, VoiceSupport_Mode: %s is not set to %s or %s, skipping udhcpc start\n",__FUNCTION__, __LINE__, cVoiceSupportMode, VOICE_SUPPORT_MODE_IPV4_ONLY, VOICE_SUPPORT_MODE_DUAL_STACK));
}
}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Race condition: The voiceDataProcessingMutex is used to protect processVoiceDhcpEvent, but startVoiceFeature() can be called multiple times concurrently (from different WAN state change events) without synchronization. This could lead to multiple concurrent attempts to create the MTA interface, subscribe to events, or start DHCP. Consider adding a guard to ensure startVoiceFeature() is idempotent or can only execute once.

Copilot uses AI. Check for mistakes.
rbusHandle_t voiceRbusHandle = NULL;
extern ANSC_HANDLE bus_handle;
const char cSubsystem[ ]= "eRT.";
static char cBaseParam[32] = {0};
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Using a static global variable cBaseParam that's populated from PSM creates potential thread-safety issues. If multiple threads call functions that depend on cBaseParam before getIfaceIndexInfo completes, they could read uninitialized or partially initialized data. Consider adding mutex protection or documenting the initialization order requirements.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 12 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1561 to +1573
if (sysevent_fd > 0)
{
if (0 != sysevent_get(sysevent_fd, sysevent_token, "wan_ifname", pIfname, iIfnameLen))
{
CcspTraceError(("%s: sysevent_get wan_ifname failed\n", __FUNCTION__));
returnStatus = ANSC_STATUS_FAILURE;
}
else
{
CcspTraceInfo(("%s: sysevent_get wan_ifname=%s\n", __FUNCTION__, pIfname));
returnStatus = ANSC_STATUS_SUCCESS;
}
}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Missing input validation: The getWanIfaceName function should validate that sysevent_fd is actually greater than 0 before using it, not just check if it's non-negative. A file descriptor of 0 is stdin and would be an invalid sysevent file descriptor. The check should be sysevent_fd >= 0 or maintain consistency with the error check pattern elsewhere in the code that checks for sysevent_fd < 0.

Suggested change
if (sysevent_fd > 0)
{
if (0 != sysevent_get(sysevent_fd, sysevent_token, "wan_ifname", pIfname, iIfnameLen))
{
CcspTraceError(("%s: sysevent_get wan_ifname failed\n", __FUNCTION__));
returnStatus = ANSC_STATUS_FAILURE;
}
else
{
CcspTraceInfo(("%s: sysevent_get wan_ifname=%s\n", __FUNCTION__, pIfname));
returnStatus = ANSC_STATUS_SUCCESS;
}
}
/* Validate sysevent_fd before using it. A value <= 0 is invalid. */
if (sysevent_fd <= 0)
{
CcspTraceError(("%s: Invalid sysevent_fd=%d\n", __FUNCTION__, sysevent_fd));
return returnStatus;
}
if (0 != sysevent_get(sysevent_fd, sysevent_token, "wan_ifname", pIfname, iIfnameLen))
{
CcspTraceError(("%s: sysevent_get wan_ifname failed\n", __FUNCTION__));
returnStatus = ANSC_STATUS_FAILURE;
}
else
{
CcspTraceInfo(("%s: sysevent_get wan_ifname=%s\n", __FUNCTION__, pIfname));
returnStatus = ANSC_STATUS_SUCCESS;
}

Copilot uses AI. Check for mistakes.
CcspTraceInfo(("%s:%d, Starting sysevent thread for Voice Mta\n", __FUNCTION__, __LINE__));
if (0 != pthread_create(&voiceMtaInit, NULL, &voiceSyseventThread, (ANSC_HANDLE) hThisObject))
{
CcspTraceError(("%s: Failed to create Voice Mta sysevent thread\n", __FUNCTION__));
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Missing pthread error check: The pthread_create call at line 1486 checks for error (returns non-zero), but doesn't return ANSC_STATUS_FAILURE or propagate the error properly - it only logs an error message and continues. This could lead to the system operating without critical voice functionality. Consider returning ANSC_STATUS_FAILURE on thread creation failure to properly signal the error.

Suggested change
CcspTraceError(("%s: Failed to create Voice Mta sysevent thread\n", __FUNCTION__));
CcspTraceError(("%s: Failed to create Voice Mta sysevent thread\n", __FUNCTION__));
return ANSC_STATUS_FAILURE;

Copilot uses AI. Check for mistakes.
getWanIfaceName(cWanIfname, sizeof(cWanIfname));
if (cWanIfname[0] == '\0')
snprintf(cWanIfname, sizeof(cWanIfname), "erouter0");

Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Missing error handling: If getWanIfaceName fails to retrieve the WAN interface name (line 197), the function defaults to "erouter0" but never checks if cWanIfname is actually valid. This could lead to attempting to create a macvlan on a non-existent interface. Consider checking if the WAN interface exists before proceeding with macvlan creation.

Suggested change
/* Verify that the WAN interface exists before attempting macvlan creation */
if (if_nametoindex(cWanIfname) == 0)
{
CcspTraceError(("%s: WAN interface %s does not exist, aborting macvlan creation\n", __FUNCTION__, cWanIfname));
return -1;
}

Copilot uses AI. Check for mistakes.
{
if (0 == access("/tmp/dumpDHCPevent.txt", F_OK))
{
FILE *fp = fopen("/tmp/dhcp_event_dump.txt", "a");
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Hardcoded file path: The debug file path "/tmp/dhcp_event_dump.txt" is hardcoded. This should be defined as a constant at the file level for better maintainability.

Copilot uses AI. Check for mistakes.
Comment on lines +111 to +116
if (ioctl(iSocketFd, SIOCGIFFLAGS, &ifr) < 0)
{
CcspTraceError(("%s: ioctl SIOCGIFFLAGS failed for interface %s\n", __FUNCTION__, pIfaceName));
close(iSocketFd);
return false;
}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Resource leak: The socket file descriptor is not closed on all error paths. If strncpy at line 107 or ioctl at line 111 succeeds but line 118 check fails, the socket remains open. Consider adding close(iSocketFd) before the return false at line 115.

Copilot uses AI. Check for mistakes.
Comment on lines +326 to +330
snprintf(cParamName, sizeof(cParamName), "ip rule add from %s table 21", pDhcpEvtData->leaseInfo.dhcpV4Msg.address);
system(cParamName);
snprintf(cParamName, sizeof(cParamName), "ip route add %s dev %s table 21", cNetworkAddrWithCidr, pDhcpEvtData->cIfaceName);
system(cParamName);
snprintf(cParamName, sizeof(cParamName), "ip route add default via %s dev %s table 21", pDhcpEvtData->leaseInfo.dhcpV4Msg.gateway, pDhcpEvtData->cIfaceName);
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Magic number: The routing table number 21 is hardcoded without explanation. This should be defined as a named constant (e.g., VOICE_ROUTING_TABLE) with a comment explaining why this specific table number is used for voice routing.

Copilot uses AI. Check for mistakes.
*/
static void readMacAddress (char * pMacAddress)
{
FILE *pFILE = fopen("/tmp/factory_nvram.data", "r");
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Hardcoded credentials location: The file path "/tmp/factory_nvram.data" is hardcoded for reading sensitive MAC address information. This file path should be defined as a constant at the file level or passed as a configuration parameter to improve maintainability and testability.

Copilot uses AI. Check for mistakes.
Comment on lines +158 to +173
void initRbusHandle(void)
{
rbusError_t rbusReturn = RBUS_ERROR_SUCCESS;
if (voiceRbusHandle != NULL)
{
CcspTraceInfo(("%s: rbus handle already initialized\n", __FUNCTION__));
return;
}
rbusReturn = rbus_open(&voiceRbusHandle, "VoiceSupportMtaInterface");
if (rbusReturn != RBUS_ERROR_SUCCESS)
{
CcspTraceError(("%s: rbus_open failed with error code %d\n", __FUNCTION__, rbusReturn));
return;
}
CcspTraceInfo(("%s: rbus_open successful\n", __FUNCTION__));
}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Race condition: The global variable voiceRbusHandle is accessed and modified without synchronization. Multiple threads could potentially call initRbusHandle() simultaneously, leading to a race condition at line 161-166. Consider using a mutex to protect the check-and-initialize pattern or use atomic operations.

Copilot uses AI. Check for mistakes.
Comment on lines +119 to +144
void getIfaceIndexInfo(void)
{
int iRetPsmGet = CCSP_SUCCESS;
char *pParamValue= NULL;

iRetPsmGet = PSM_Get_Record_Value2(bus_handle, cSubsystem, DHCPv4_VOICE_SUPPORT_PARAM, NULL, &pParamValue);
if (iRetPsmGet != CCSP_SUCCESS)
{
CcspTraceError(("%s: PSM_Get_Record_Value2 failed for param %s with error code %d\n", __FUNCTION__, DHCPv4_VOICE_SUPPORT_PARAM,
iRetPsmGet));
/* Set a safe default base parameter to avoid constructing invalid RBUS paths later. */
snprintf(cBaseParam, sizeof(cBaseParam), "%s", DHCP_MGR_DHCPv4_TABLE);
return;
}
else
{
CcspTraceInfo(("%s: PSM_Get_Record_Value2 successful for param %s with value %s\n", __FUNCTION__, DHCPv4_VOICE_SUPPORT_PARAM,
pParamValue));
if (strlen(pParamValue) == 0)
{
CcspTraceWarning(("%s: Retrieved empty value for param %s, using default base parameter\n", __FUNCTION__, DHCPv4_VOICE_SUPPORT_PARAM));
snprintf(cBaseParam, sizeof(cBaseParam), "%s", DHCP_MGR_DHCPv4_TABLE);
}
else
{
snprintf(cBaseParam, sizeof(cBaseParam), "%s",pParamValue);
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Race condition with global cBaseParam: The static variable cBaseParam is set by getIfaceIndexInfo() and read by multiple functions (enableDhcpv4ForMta, eventSubscriptionThread). If multiple threads call these functions simultaneously before getIfaceIndexInfo() completes, they could read an empty or partially initialized cBaseParam. Consider protecting access to cBaseParam with a mutex or ensuring initialization is complete before any threads are created.

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

//Commend out the broadcom patch changes for now, will be requried to test basic voice functionality supported by broadcom.
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Duplicate spelling errors across multiple files: The same spelling errors "Commend" (should be "Comment") and "requried" (should be "required") appear in at least 5 different files. These should all be corrected for consistency and professionalism.

Copilot uses AI. Check for mistakes.
Reason for change:Addressing the code review comments
Test Procedure: verify the voice is initialized or not
Risks: High
Priority: P1
</parameters>
</object>

<?ifdef VOICE_MTA_SUPPORT?>

Choose a reason for hiding this comment

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

we don't need these TR181, comment out these dml's

Reason for change:Addressing the code review comments
Test Procedure: verify the voice is initialized or not
Risks: High
Priority: P1
Copilot AI review requested due to automatic review settings February 15, 2026 07:30
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 17 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return;
}
pthread_detach(dhcpEventThreadId);
usleep(10000); // Sleep for 10ms to allow thread to start
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

Questionable sleep in event handler: The usleep(10000) call after pthread_detach appears to be a workaround to allow the thread to start. This is a race condition mitigation that doesn't guarantee the thread will actually start. Since the thread is detached and allocated data is passed to it, this could still result in use-after-free if the event handler returns and is freed before the thread accesses pDhcpEvtData. Consider using proper synchronization or removing the sleep if it's not necessary.

Suggested change
usleep(10000); // Sleep for 10ms to allow thread to start

Copilot uses AI. Check for mistakes.
char cParamName[64] = {0};
char cPartnerId[64] = { 0 };
syscfg_get(NULL, "PartnerID", cPartnerId, sizeof(cPartnerId));
if ('\0' != cPartnerId[0] && strcmp(cPartnerId, "comcast") == 0)
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

Case-sensitive partner ID comparison: The partner ID comparison uses strcmp which is case-sensitive. If the PartnerID syscfg value is stored as "Comcast" or "COMCAST", the comparison will fail and DHCPv4 won't be configured. Consider using strcasecmp for case-insensitive comparison to be more robust.

Suggested change
if ('\0' != cPartnerId[0] && strcmp(cPartnerId, "comcast") == 0)
if ('\0' != cPartnerId[0] && strcasecmp(cPartnerId, "comcast") == 0)

Copilot uses AI. Check for mistakes.
Comment on lines +265 to +274
static uint8_t cbSubsIfInfo(char *pIntfName, uint8_t enable)
{
if (enable)
{
/* Save voice interface selection */
strncpy(voiceInterface, pIntfName, sizeof(voiceInterface));
}

return 1;
}
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

Missing return value documentation: The function cbSubsIfInfo always returns 1 without documenting what the return value represents or whether returning 0 would indicate an error. The function documentation or comment should explain the meaning of the return value.

Copilot uses AI. Check for mistakes.
char cParamName[64] = {0};
char cPartnerId[64] = { 0 };
syscfg_get(NULL, "PartnerID", cPartnerId, sizeof(cPartnerId));
if ('\0' != cPartnerId[0] && strcmp(cPartnerId, "comcast") == 0)
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

Redundant check: The condition '\0' != cPartnerId[0] is redundant because if strlen(cPartnerId) was 0 (checked by the following strcmp), cPartnerId[0] would already be '\0'. Consider simplifying to just: if (strcmp(cPartnerId, "comcast") == 0)

Suggested change
if ('\0' != cPartnerId[0] && strcmp(cPartnerId, "comcast") == 0)
if (strcmp(cPartnerId, "comcast") == 0)

Copilot uses AI. Check for mistakes.
Comment on lines +299 to +302
if (pFirewallRule->enable)
{
snprintf(command, sizeof(command), "-A INPUT -p %s -i %s --dport %u -j ACCEPT",
protocol, pFirewallRule->ifName, pFirewallRule->destinationPort);
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

Missing bounds check on port number: The destinationPort field is used directly in the firewall command without validation. If it's 0 or exceeds 65535, it could create an invalid firewall rule. Consider validating: if (pFirewallRule->destinationPort == 0 || pFirewallRule->destinationPort > 65535) return error.

Copilot uses AI. Check for mistakes.
}
addIpRouteDetails(pDhcpEvtData);
initializeVoiceSupport(pDhcpEvtData);

Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

Trailing whitespace: There is trailing whitespace at the end of this line which should be removed to maintain clean code formatting.

Copilot uses AI. Check for mistakes.
Comment on lines +1484 to 1493
}
#elif defined(ENABLE_ETH_WAN)
sysevent_fd = sysevent_open("127.0.0.1", SE_SERVER_WELL_KNOWN_PORT, SE_VERSION, "WAN State", &sysevent_token);
pthread_t MtaInit;
#if defined (EROUTER_DHCP_OPTION_MTA)
CcspTraceInfo(("%s %d Starting sysevent thread for DHCP option 122/2171 \n", __FUNCTION__, __LINE__));
pthread_create(&MtaInit, NULL, &Mta_Sysevent_thread_Dhcp_Option, (ANSC_HANDLE) hThisObject);
#else
CcspTraceInfo(("%s %d Starting sysevent thread for WAN state \n", __FUNCTION__, __LINE__));
pthread_create(&MtaInit, NULL, &Mta_Sysevent_thread, (ANSC_HANDLE) hThisObject);
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

Missing error handling: When pthread_create fails, the function only logs an error but continues execution and returns ANSC_STATUS_SUCCESS. This is inconsistent with the sysevent_open error handling above which returns ANSC_STATUS_FAILURE. Consider returning ANSC_STATUS_FAILURE when thread creation fails to properly indicate initialization failure.

Suggested change
}
#elif defined(ENABLE_ETH_WAN)
sysevent_fd = sysevent_open("127.0.0.1", SE_SERVER_WELL_KNOWN_PORT, SE_VERSION, "WAN State", &sysevent_token);
pthread_t MtaInit;
#if defined (EROUTER_DHCP_OPTION_MTA)
CcspTraceInfo(("%s %d Starting sysevent thread for DHCP option 122/2171 \n", __FUNCTION__, __LINE__));
pthread_create(&MtaInit, NULL, &Mta_Sysevent_thread_Dhcp_Option, (ANSC_HANDLE) hThisObject);
#else
CcspTraceInfo(("%s %d Starting sysevent thread for WAN state \n", __FUNCTION__, __LINE__));
pthread_create(&MtaInit, NULL, &Mta_Sysevent_thread, (ANSC_HANDLE) hThisObject);
return ANSC_STATUS_FAILURE;
}
#elif defined(ENABLE_ETH_WAN)
sysevent_fd = sysevent_open("127.0.0.1", SE_SERVER_WELL_KNOWN_PORT, SE_VERSION, "WAN State", &sysevent_token);
pthread_t MtaInit;
#if defined (EROUTER_DHCP_OPTION_MTA)
CcspTraceInfo(("%s %d Starting sysevent thread for DHCP option 122/2171 \n", __FUNCTION__, __LINE__));
if (0 != pthread_create(&MtaInit, NULL, &Mta_Sysevent_thread_Dhcp_Option, (ANSC_HANDLE) hThisObject))
{
CcspTraceError(("%s: Failed to create MTA sysevent thread for DHCP option 122/2171\n", __FUNCTION__));
return ANSC_STATUS_FAILURE;
}
#else
CcspTraceInfo(("%s %d Starting sysevent thread for WAN state \n", __FUNCTION__, __LINE__));
if (0 != pthread_create(&MtaInit, NULL, &Mta_Sysevent_thread, (ANSC_HANDLE) hThisObject))
{
CcspTraceError(("%s: Failed to create MTA sysevent thread for WAN state\n", __FUNCTION__));
return ANSC_STATUS_FAILURE;
}

Copilot uses AI. Check for mistakes.
* @param[in] pIfaceName Name of the MTA network interface for which
* DHCPv4 should be enabled.
*/
void enableDhcpv4ForMta(const char * pIfaceName)
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

Inconsistent function naming convention: The function name uses camelCase (enableDhcpv4ForMta) which is inconsistent with other function names in the file that use camelCase but with different capitalization for abbreviations. Looking at the codebase, HAL-related functions use mixed conventions, but for consistency within this module, consider using enableDhcpV4ForMta (capital V4) to match the naming of other functions like subscribeDhcpClientEvents.

Copilot uses AI. Check for mistakes.
}

CcspTraceInfo(("%s:%d, DHCP Client Events Handler Thread started\n", __FUNCTION__, __LINE__));
DhcpEventData_t *pDhcpEvtData = (DhcpEventData_t *)pArg;
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

Potential null pointer dereference: The function casts pArg to DhcpEventData_t * without checking if it's NULL until after the cast. While there is a NULL check immediately after, the parameter documentation and early NULL check are good practices. The current implementation is safe but could be clearer by checking before the cast.

Suggested change
DhcpEventData_t *pDhcpEvtData = (DhcpEventData_t *)pArg;
DhcpEventData_t *pDhcpEvtData = (DhcpEventData_t *)pArg;
if (NULL == pDhcpEvtData)
{
CcspTraceError(("%s: NULL DHCP event data after cast\n", __FUNCTION__));
return NULL;
}

Copilot uses AI. Check for mistakes.
if (enable)
{
/* Save voice interface selection */
strncpy(voiceInterface, pIntfName, sizeof(voiceInterface));
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

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

Buffer overflow potential: The voiceInterface buffer is 32 bytes, and strncpy copies from pIntfName without checking its length first. If pIntfName is NULL or points to an invalid address, this will crash. Although strncpy limits the copy, the size check should happen before the copy. Also, the strncpy call doesn't ensure null-termination. Consider: if (pIntfName && strlen(pIntfName) < sizeof(voiceInterface)) { strncpy(...); voiceInterface[sizeof(voiceInterface)-1] = '\0'; }

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants