Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
89aaf6b
RDKB-777777: Get the udhcpc arguments for virtual mta interface
Amaresh-Kotekal Nov 27, 2025
48d8563
RDKB-777777: Get the udhcpc arguments for macvlan mta interface
Amaresh-Kotekal Dec 12, 2025
0bee820
RDKB-777777: Get the udhcpc arguments for macvlan mta interface
Dec 20, 2025
e923264
RDKB-777777: Get the udhcpc arguments for macvlan mta interface
Amaresh-Kotekal Dec 23, 2025
dedfdf0
RDKB-777777: Get the udhcpc arguments for macvlan mta interface
Amaresh-Kotekal Dec 24, 2025
05bedb4
RDKB-62812:Create Virtual Interface for voice and initialize DHCP
Amaresh-Kotekal Dec 25, 2025
e0dd077
RDKB-62812:Create Virtual Interface for voice and initialize DHCP
Amaresh-Kotekal Jan 7, 2026
afd0465
RDKB-62812:Create Virtual Interface for voice and initialize DHCP
Amaresh-Kotekal Jan 13, 2026
ba58939
RDKB-62812:Create Virtual Interface for voice and initialize DHCP
Amaresh-Kotekal Jan 14, 2026
e92cc75
RDKB-62812:Create Virtual Interface for voice and initialize DHCP
Amaresh-Kotekal Jan 16, 2026
bf25df6
RDKB-62812:Create Virtual Interface for voice and initialize DHCP
Amaresh-Kotekal Jan 21, 2026
b9ceec9
RDKB-62812:Create Virtual Interface for voice and initialize DHCP
Amaresh-Kotekal Jan 28, 2026
bc3f341
RDKB-62813:DHCP Data Handling and Initialization of voice
Amaresh-Kotekal Jan 31, 2026
b290099
RDKB-62813:DHCP Data Handling and Initialization of voice
Amaresh-Kotekal Feb 4, 2026
8f9b15d
RDKB-62813:DHCP Data Handling and Initialization of voice
Amaresh-Kotekal Feb 6, 2026
a918674
RDKB-62813:DHCP Data Handling and Initialization of voice
Amaresh-Kotekal Feb 6, 2026
322656a
RDKB-62813:DHCP Data Handling and Initialization of voice
Amaresh-Kotekal Feb 7, 2026
97c65e6
RDKB-62813:DHCP Data Handling and Initialization of voice
Amaresh-Kotekal Feb 13, 2026
a88bf6e
RDKB-62813:DHCP Data Handling and Initialization of voice
Amaresh-Kotekal Feb 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ AC_ARG_ENABLE([unitTestDockerSupport],
[echo "Docker support is disabled"])
AM_CONDITIONAL([UNIT_TEST_DOCKER_SUPPORT], [test x$UNIT_TEST_DOCKER_SUPPORT = xtrue])

# Checks for Voice_support
AC_ARG_ENABLE([voice_mta_support],
[ --enable-voice_mta_support=val Turn on voice support, val=yes or no],
[case "${enableval}" in
yes) voice_support=yes;;
no) voice_support=no;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-voice_mta_support]) ;;
esac],[voice_mta_support=no])
AM_CONDITIONAL(VOICE_MTA_SUPPORT, test x"$voice_support" = x"yes")

AC_PREFIX_DEFAULT(`pwd`)
AC_ENABLE_SHARED
AC_DISABLE_STATIC
Expand Down
162 changes: 162 additions & 0 deletions source/TR-181/integration_src.shared/cosa_x_cisco_com_mta_apis.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@
#include "safec_lib_common.h"
#include "sysevent/sysevent.h"
#include "ctype.h"
#if defined (VOICE_MTA_SUPPORT)
#include "voice_dhcp_hal.h"
#include "bcm_generic_hal.h"
#endif


// #include "cosa_x_cisco_com_mta_internal.h"
Expand Down Expand Up @@ -164,6 +168,145 @@ int mtaReapplytr104Conf(void)

#endif // MTA_TR104SUPPORT

#if defined (VOICE_MTA_SUPPORT)

/*
* @brief Set the voice interface name in brcm based on syscfg value.
* If the syscfg value is not set, default to "mta0".
* If the default interface name from bcm is different from the syscfg value, update it in bcm using setParameterValues API.
*/
void setVoiceIfname(void)
{
char cVoiceSupportIfaceName[32] = { 0 };
syscfg_get(NULL, "VoiceSupport_IfaceName",cVoiceSupportIfaceName, sizeof(cVoiceSupportIfaceName));
AnscTraceInfo(("%s:%d, VoiceSupport_IfaceName from syscfg is %s\n", __FUNCTION__, __LINE__, cVoiceSupportIfaceName));

if (0 == strlen(cVoiceSupportIfaceName))
{
AnscTraceError(("VoiceSupport_IfaceName is not set in syscfg\n"));
snprintf(cVoiceSupportIfaceName, sizeof(cVoiceSupportIfaceName), "%s", "mta0");
AnscTraceInfo(("Defaulting VoiceSupport_IfaceName to %s\n", cVoiceSupportIfaceName));
}
char cFullpath[256] = "Device.Services.VoiceService.1.X_BROADCOM_COM_BoundIfName";
char cValue[128] = { 0 };

BcmRet rc;
char *nameArray[1] = { cFullpath };
BcmGenericParamInfo *getParamInfoArray = NULL;
UINT32 numParamInfo = 0;

rc = bcm_generic_getParameterValues((const char **)nameArray, 1, FALSE, 0,
&getParamInfoArray, &numParamInfo);
if (BCMRET_SUCCESS == rc)
{
if (1 == numParamInfo)
{
AnscTraceInfo(("%s:%d, Value:%s\n", __FUNCTION__, __LINE__, getParamInfoArray[0].value));
snprintf(cValue, sizeof(cValue), "%s", getParamInfoArray[0].value);
}
bcm_generic_freeParamInfoArray(&getParamInfoArray, numParamInfo);
}

if (BCMRET_SUCCESS != rc || strlen(cValue) == 0 || strcmp(cVoiceSupportIfaceName, cValue) != 0)
{
BcmGenericParamInfo setParamInfoArray[1] = { 0 };

/* Fill config structure */
setParamInfoArray[0].fullpath = cFullpath;
setParamInfoArray[0].type = "string";
setParamInfoArray[0].value = cVoiceSupportIfaceName;

AnscTraceInfo(("%s:%d, Setting %s to %s\n", __FUNCTION__, __LINE__, cFullpath, cVoiceSupportIfaceName));
rc = bcm_generic_setParameterValues(setParamInfoArray, 1, 0);
if (BCMRET_SUCCESS != rc) {
AnscTraceError(("setParamString: bcm_generic_setParameterValues failed for %s\n",
cFullpath));
}
}
}

/*
* @brief Set firewall rule for voice interface using sysevent. If pCommand is NULL or empty, the firewall rule will be removed.
*/
static void setFirewallRule(char * pCommand, uint8_t ui8Enable)
{
int syseventFd = -1;
token_t syseventToken;

syseventFd = sysevent_open("127.0.0.1", SE_SERVER_WELL_KNOWN_PORT, SE_VERSION, "Firewall", &syseventToken);
if (syseventFd < 0)
{
AnscTraceError(("%s:%d - sysevent_open failed\n", __FUNCTION__, __LINE__));
return;
}

AnscTraceInfo(("%s: ui8Enable=%d\n", __FUNCTION__, ui8Enable));
AnscTraceInfo(("%s: Calling sysevent command: %s\n", __FUNCTION__, pCommand));
if (ui8Enable)
{
if (NULL == pCommand || '\0' == pCommand[0])
{
AnscTraceError(("%s: Invalid command string\n", __FUNCTION__));
sysevent_close(syseventFd, syseventToken);
return;
}
sysevent_set(syseventFd, syseventToken, "VoiceIpRule", pCommand, 0);
}
else
sysevent_unset(syseventFd, syseventToken, "VoiceIpRule");

AnscTraceInfo(("%s: Calling sysevent firewall-restart\n", __FUNCTION__));
sysevent_set(syseventFd, syseventToken, "firewall-restart", "", 0);
sysevent_close(syseventFd, syseventToken);
}

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));
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.

Buffer overflow risk: strncpy(voiceInterface, pIntfName, sizeof(voiceInterface)) at line 895 doesn't guarantee null-termination if pIntfName is 32 bytes or longer. This could cause issues when voiceInterface is later used as a string. Use snprintf or ensure explicit null-termination.

Suggested change
strncpy(voiceInterface, pIntfName, sizeof(voiceInterface));
strncpy(voiceInterface, pIntfName, sizeof(voiceInterface));
voiceInterface[sizeof(voiceInterface) - 1] = '\0';

Copilot uses AI. Check for mistakes.
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.
}

return 1;
}
Comment on lines +263 to +274
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 +265 to +274
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.

static uint8_t cbGetCertInfo(VoiceCertificateInfoType *pCertInfo)
{
UNREFERENCED_PARAMETER(pCertInfo);

return 0;
}

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))
{
snprintf(protocol, sizeof(protocol), "%s", "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);
Comment on lines +299 to +302
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.
}
Comment on lines 283 to 303
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.
Comment on lines +299 to +303
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 command injection vulnerability: The firewall command is constructed using protocol and ifName from pFirewallRule without validation. If these fields contain shell metacharacters, they could enable command injection. Consider validating the protocol (should be "TCP" or "UDP" only) and interface name (should match expected pattern) before using them in the command string.

Copilot uses AI. Check for mistakes.
setFirewallRule(command, pFirewallRule->enable);
return 1;
}


#endif /* VOICE_MTA_SUPPORT */

ANSC_STATUS
CosaDmlMTAInit
Expand All @@ -177,8 +320,27 @@ CosaDmlMTAInit

// PCOSA_DATAMODEL_MTA pMyObject = (PCOSA_DATAMODEL_MTA)phContext;

AnscTraceInfo(("CosaDmlMTAInit: mta_hal_InitDB() \n"));

if ( mta_hal_InitDB() == RETURN_OK )
{
#if defined (VOICE_MTA_SUPPORT)
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 voice callbacks won't be registered. Consider using strcasecmp for case-insensitive comparison to be more robust.

Copilot uses AI. Check for mistakes.
{
AnscTraceInfo(("CosaDmlMTAInit: voice_hal_register_cb() \n"));
setVoiceIfname();
/* Register callback functions */
voice_hal_register_cb(cbSubsIfInfo, cbSetFirewallRule, cbGetCertInfo);
}
else
{
AnscTraceInfo(("CosaDmlMTAInit: Not registering callbacks since partnerId is %s\n", cPartnerId));
}
#endif
return ANSC_STATUS_SUCCESS;
}
else
return ANSC_STATUS_FAILURE;
}
Expand Down
4 changes: 4 additions & 0 deletions source/TR-181/middle_layer_src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ libCcspMtaAgent_middle_layer_src_la_CFLAGS = $(AM_CFLAGS) $(MTA_CFLAGS)
libCcspMtaAgent_middle_layer_src_la_CPPFLAGS = -I$(top_srcdir)/source/TR-181/board_sbapi -I$(top_srcdir)/source/TR-181/middle_layer_src -I$(top_srcdir)/source/TR-181/include -I$(top_srcdir)/source/Custom
libCcspMtaAgent_middle_layer_src_la_SOURCES = cosa_x_cisco_com_mta_internal.c plugin_main.c plugin_main_apis.c cosa_x_cisco_com_mta_dml.c ../../MtaAgentSsp/TR104_webconfig.c
libCcspMtaAgent_middle_layer_src_la_LDFLAGS = -lccsp_common -lhal_mta -lmsgpackc

if VOICE_MTA_SUPPORT
libCcspMtaAgent_middle_layer_src_la_SOURCES += cosa_rbus_apis.c cosa_voice_apis.c
endif
Loading