diff --git a/configure.ac b/configure.ac index 6072d20..41492e9 100644 --- a/configure.ac +++ b/configure.ac @@ -89,6 +89,18 @@ AC_ARG_ENABLE([gtestapp], [echo "Gtestapp is disabled"]) AM_CONDITIONAL([WITH_GTEST_SUPPORT], [test x$GTEST_SUPPORT_ENABLED = xtrue]) +AC_ARG_ENABLE([wanunificationsupport], + AS_HELP_STRING([--enable-wanunificationsupport],[enable wan unification support (default is no)]), + [ + case "${enableval}" in + yes) WAN_UNIFICATION_SUPPORT_ENABLED=true;; + no) WAN_UNIFICATION_SUPPORT_ENABLED=false;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-wanunificationsupport ]);; + esac + ], + [echo "mapt unification is disabled"]) +AM_CONDITIONAL(WAN_UNIFICATION_ENABLED, test "x$WAN_UNIFICATION_SUPPORT_ENABLED" = xtrue) + dnl Checks for header files. AC_CHECK_HEADERS([limits.h memory.h stdlib.h string.h sys/socket.h unistd.h]) diff --git a/source/TR-181/include/wanmgr_dml.h b/source/TR-181/include/wanmgr_dml.h index 1b86e29..83c7167 100644 --- a/source/TR-181/include/wanmgr_dml.h +++ b/source/TR-181/include/wanmgr_dml.h @@ -313,7 +313,7 @@ typedef struct _WANMGR_IPV4_DATA uint32_t downstreamCurrRate; /** Downstream rate */ char dhcpServerId[BUFLEN_64]; /** Dhcp server id */ char dhcpState[BUFLEN_64]; /** Dhcp state. */ - uint32_t leaseTime; /** Lease time, , if addressAssigned==TRUE */ + uint32_t leaseTime; /** Lease time */ #endif } WANMGR_IPV4_DATA; @@ -340,6 +340,11 @@ typedef struct _WANMGR_IPV6_DATA #endif } WANMGR_IPV6_DATA; +typedef struct _WANMGR_IPV6_RA_DATA +{ + char defaultRoute[INET6_ADDRSTRLEN]; + uint32_t defRouteLifeTime; +} WANMGR_IPV6_RA_DATA; typedef struct _DML_WANIFACE_IP { @@ -355,7 +360,6 @@ typedef struct _DML_WANIFACE_IP BOOL RestartConnectivityCheck; BOOL WCC_TypeChanged; // Flag to notify change in ConnectivityCheckType BOOL RefreshDHCP; - BOOL RestartV6Client; //This is a workaround to restart dhcpv6 client for the platform where PAM configures IPv6. !FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE DML_WAN_IP_MODE Mode; DML_WAN_IP_PREFERRED_MODE PreferredMode; DML_WAN_IP_PREFERRED_MODE SelectedMode; @@ -368,6 +372,7 @@ typedef struct _DML_WANIFACE_IP BOOL Ipv6Renewed; WANMGR_IPV4_DATA Ipv4Data; WANMGR_IPV6_DATA Ipv6Data; + WANMGR_IPV6_RA_DATA Ipv6Route; ipc_dhcpv4_data_t* pIpcIpv4Data; ipc_dhcpv6_data_t* pIpcIpv6Data; UINT Dhcp4cPid; diff --git a/source/TR-181/middle_layer_src/wanmgr_rbus_handler_apis.c b/source/TR-181/middle_layer_src/wanmgr_rbus_handler_apis.c index 810f7a4..574434e 100644 --- a/source/TR-181/middle_layer_src/wanmgr_rbus_handler_apis.c +++ b/source/TR-181/middle_layer_src/wanmgr_rbus_handler_apis.c @@ -1661,33 +1661,40 @@ static void CPEInterface_AsyncMethodHandler( { char AliasName[64] = {0}; snprintf(AliasName, sizeof(AliasName), "REMOTE_%s" , pValue); - strncpy( pWanIfaceData->AliasName, AliasName,sizeof(pWanIfaceData->AliasName)-1 ); - //Set Alias name of Virtual interface - strncpy( pWanIfaceData->VirtIfList->Alias, AliasName,sizeof(pWanIfaceData->VirtIfList->Alias)-1 ); - //Register the interface again if Alias changed - int rc = -1; - rc = rbusTable_registerRow(rbusHandle, WANMGR_INFACE_TABLE, (cpeInterfaceIndex+1), AliasName); - if(rc != RBUS_ERROR_SUCCESS) + if(strcmp(AliasName,pWanIfaceData->AliasName) !=0) { - CcspTraceError(("%s %d - Iterface(%d) Table (%s) Registartion failed \n", - __FUNCTION__, __LINE__, (cpeInterfaceIndex+1), WANMGR_INFACE_TABLE)); - } -#if defined(WAN_MANAGER_UNIFICATION_ENABLED) - char tmpVIfTableName[256] = {0}; - for(int VirId=0; VirId< pWanDmlIfaceData->data.NoOfVirtIfs; VirId++) - { - snprintf(tmpVIfTableName, sizeof(tmpVIfTableName), WANMGR_VIRTUAL_INFACE_TABLE_ALIAS, AliasName); - rc = rbusTable_registerRow(rbusHandle, tmpVIfTableName, (VirId+1), AliasName); //TODO: NEW_DESIGN get Alias name for virtual table + strncpy( pWanIfaceData->AliasName, AliasName,sizeof(pWanIfaceData->AliasName)-1 ); + //Set Alias name of Virtual interface + strncpy( pWanIfaceData->VirtIfList->Alias, AliasName,sizeof(pWanIfaceData->VirtIfList->Alias)-1 ); + //Register the interface again if Alias changed + char param_name[256] = {0}; + snprintf(param_name,sizeof(param_name), "%s.%d", WANMGR_INFACE_TABLE, (cpeInterfaceIndex+1)); + rbusTable_unregisterRow(rbusHandle, param_name); + + int rc = -1; + rc = rbusTable_registerRow(rbusHandle, WANMGR_INFACE_TABLE, (cpeInterfaceIndex+1), AliasName); if(rc != RBUS_ERROR_SUCCESS) { - CcspTraceError(("%s %d - VirtualInterface(%d) Table (%s) Registartion failed, Error=%d \n", __FUNCTION__, __LINE__, (VirId+1), tmpVIfTableName, rc)); + CcspTraceError(("%s %d - Iterface(%d) Table (%s) Registartion failed \n", + __FUNCTION__, __LINE__, (cpeInterfaceIndex+1), WANMGR_INFACE_TABLE)); } - else +#if defined(WAN_MANAGER_UNIFICATION_ENABLED) + char tmpVIfTableName[256] = {0}; + for(int VirId=0; VirId< pWanDmlIfaceData->data.NoOfVirtIfs; VirId++) { - CcspTraceInfo(("%s %d - VirtualInterface(%d) Table (%s) Registartion Successfully, AliasName(%s)\n", __FUNCTION__, __LINE__, (VirId+1), tmpVIfTableName, AliasName)); + snprintf(tmpVIfTableName, sizeof(tmpVIfTableName), WANMGR_VIRTUAL_INFACE_TABLE_ALIAS, AliasName); + rc = rbusTable_registerRow(rbusHandle, tmpVIfTableName, (VirId+1), AliasName); //TODO: NEW_DESIGN get Alias name for virtual table + if(rc != RBUS_ERROR_SUCCESS) + { + CcspTraceError(("%s %d - VirtualInterface(%d) Table (%s) Registartion failed, Error=%d \n", __FUNCTION__, __LINE__, (VirId+1), tmpVIfTableName, rc)); + } + else + { + CcspTraceInfo(("%s %d - VirtualInterface(%d) Table (%s) Registartion Successfully, AliasName(%s)\n", __FUNCTION__, __LINE__, (VirId+1), tmpVIfTableName, AliasName)); + } } - } #endif + } } else if( WANMGR_PHY_STATUS_CHECK ) { @@ -1888,7 +1895,7 @@ ANSC_STATUS WanMgr_Configure_TAD_WCC(DML_VIRTUAL_IFACE *p_VirtIf, WCC_EVENT Eve snprintf(pTADEvent->IPv4_DNS_Servers, sizeof(pTADEvent->IPv4_DNS_Servers), "%s,%s",p_VirtIf->IP.Ipv4Data.dnsServer,p_VirtIf->IP.Ipv4Data.dnsServer1); snprintf(pTADEvent->IPv4_Gateway, sizeof(pTADEvent->IPv4_Gateway), "%s",p_VirtIf->IP.Ipv4Data.gateway); snprintf(pTADEvent->IPv6_DNS_Servers, sizeof(pTADEvent->IPv6_DNS_Servers), "%s,%s",p_VirtIf->IP.Ipv6Data.nameserver,p_VirtIf->IP.Ipv6Data.nameserver1); - //TODO: Add Ipv6 gateway address after integrating with DHCP manager. Currently, wanmanager doesn't have information of IPv6 gateway address + snprintf(pTADEvent->IPv6_Gateway, sizeof(pTADEvent->IPv6_Gateway), "%s",p_VirtIf->IP.Ipv6Route.defaultRoute,p_VirtIf->IP.Ipv6Route.defaultRoute); pTADEvent->Event = Event; //Run in thread to avoid mutex deadlock between WanManager and rbus handle @@ -1959,26 +1966,6 @@ void *WanMgr_Configure_WCC_Thread(void *arg) snprintf(pTADEvent->IPv6_DNS_Servers, sizeof(pTADEvent->IPv6_DNS_Servers), "%s,", strtok(MeshWANInterfaceUla, "/")); snprintf(pTADEvent->IPv6_Gateway, sizeof(pTADEvent->IPv6_Gateway), "%s", strtok(MeshWANInterfaceUla, "/")); } - else //TODO: Workaround to fetch Ipv6 gateway address from the routing table. This should be removed after integrating DHCPmanager - { - FILE *fp_route; - char command[BUFLEN_256] = {0}; - char buffer[BUFLEN_256] ={0}; - snprintf(command, sizeof(command), "ip -6 route show default | grep %s | awk '{print $3}'", pTADEvent->IfaceName); - fp_route = popen(command, "r"); - if(fp_route != NULL) - { - if (fgets(buffer, BUFLEN_256, fp_route) != NULL) - { - char *token = strtok(buffer, "\n"); // get string up until newline character - if (token) - { - strncpy(pTADEvent->IPv6_Gateway, token, sizeof(pTADEvent->IPv6_Gateway)-1); - } - } - pclose(fp_route); - } - } // set IPv6 nameserver list CcspTraceInfo(("%s %d: IPv6_DNS_Servers %s \n", __FUNCTION__, __LINE__, pTADEvent->IPv6_DNS_Servers)); diff --git a/source/TR-181/middle_layer_src/wanmgr_rdkbus_apis.c b/source/TR-181/middle_layer_src/wanmgr_rdkbus_apis.c index 0b109ef..a0518fe 100644 --- a/source/TR-181/middle_layer_src/wanmgr_rdkbus_apis.c +++ b/source/TR-181/middle_layer_src/wanmgr_rdkbus_apis.c @@ -261,13 +261,11 @@ int get_Virtual_Interface_FromPSM(ULONG instancenum, ULONG virtInsNum ,DML_VIRTU pVirtIf->Enable = TRUE; } -#if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) /* TODO: This is a workaround for the platforms using same Wan Name.*/ _ansc_memset(param_name, 0, sizeof(param_name)); _ansc_memset(param_value, 0, sizeof(param_value)); _ansc_sprintf(param_name, PSM_WANMANAGER_IF_VIRIF_NAME, instancenum, (virtInsNum + 1)); retPsmGet = WanMgr_RdkBus_GetParamValuesFromDB(param_name,param_value,sizeof(param_value)); AnscCopyString(pVirtIf->Name, param_value); -#endif _ansc_memset(param_name, 0, sizeof(param_name)); _ansc_memset(param_value, 0, sizeof(param_value)); @@ -530,13 +528,11 @@ int write_Virtual_Interface_ToPSM(ULONG instancenum, ULONG virtInsNum ,DML_VIRTU _ansc_sprintf(param_name, PSM_WANMANAGER_IF_VIRIF_ENABLE, instancenum, (virtInsNum + 1)); WanMgr_RdkBus_SetParamValuesToDB(param_name,param_value); -#if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) /* TODO: This is a workaround for the platforms using same Wan Name.*/ memset(param_value, 0, sizeof(param_value)); memset(param_name, 0, sizeof(param_name)); AnscCopyString(param_value, pVirtIf->Name); _ansc_sprintf(param_name, PSM_WANMANAGER_IF_VIRIF_NAME, instancenum, (virtInsNum + 1)); WanMgr_RdkBus_SetParamValuesToDB(param_name,param_value); -#endif memset(param_value, 0, sizeof(param_value)); memset(param_name, 0, sizeof(param_name)); diff --git a/source/TR-181/middle_layer_src/wanmgr_rdkbus_utils.c b/source/TR-181/middle_layer_src/wanmgr_rdkbus_utils.c index 6f71480..0a9b95c 100644 --- a/source/TR-181/middle_layer_src/wanmgr_rdkbus_utils.c +++ b/source/TR-181/middle_layer_src/wanmgr_rdkbus_utils.c @@ -967,14 +967,14 @@ ANSC_STATUS WanMgr_RdkBus_setDhcpv6DnsServerInfo(void) #if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) ANSC_STATUS WanMgr_RdkBus_setWanIpInterfaceData(DML_VIRTUAL_IFACE* pVirtIf) { - ANSC_STATUS retStatus = ANSC_STATUS_FAILURE; + ANSC_STATUS retStatus = ANSC_STATUS_SUCCESS; char dmQuery[BUFLEN_256] = {0}; snprintf(dmQuery, sizeof(dmQuery)-1, "%s.LowerLayers", pVirtIf->IP.Interface); if(pVirtIf->PPP.Enable == TRUE) { retStatus = WanMgr_RdkBus_SetParamValues( PAM_COMPONENT_NAME, PAM_DBUS_PATH, dmQuery, pVirtIf->PPP.Interface, ccsp_string, TRUE ); CcspTraceInfo(("%s %d - Updating %s => %s\n", __FUNCTION__, __LINE__,dmQuery, pVirtIf->PPP.Interface)); - }else + }else if(pVirtIf->VLAN.Enable == TRUE) { retStatus = WanMgr_RdkBus_SetParamValues( PAM_COMPONENT_NAME, PAM_DBUS_PATH, dmQuery, pVirtIf->VLAN.VLANInUse, ccsp_string, TRUE ); CcspTraceInfo(("%s %d - Updating %s => %s\n", __FUNCTION__, __LINE__,dmQuery,pVirtIf->VLAN.VLANInUse)); diff --git a/source/WanManager/DHCPv6cMsgHandler/dhcpv6c_msg_apis.c b/source/WanManager/DHCPv6cMsgHandler/dhcpv6c_msg_apis.c new file mode 100644 index 0000000..172d1b4 --- /dev/null +++ b/source/WanManager/DHCPv6cMsgHandler/dhcpv6c_msg_apis.c @@ -0,0 +1,737 @@ +/* + * If not stated otherwise in this file or this component's Licenses.txt file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/********************************************************************** + Copyright [2014] [Cisco Systems, Inc.] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +**********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ccsp_psm_helper.h" +#include "ansc_platform.h" +#include +#include "ccsp_psm_helper.h" +#include "sys_definitions.h" +#include "secure_wrapper.h" + +#include "wanmgr_dml.h" +#include "dhcpv6c_msg_apis.h" + +/* + * Macro definitions + */ + +#define STRING_TO_HEX(pStr) ( (pStr-'a'<0)? (pStr-'A'<0)? pStr-'0' : pStr-'A'+10 : pStr-'a'+10 ) + +#define ERR_CHK(x) +#define CCSP_COMMON_FIFO "/tmp/ccsp_common_fifo" + +extern int sysevent_fd; +extern token_t sysevent_token; + +/* + * Static function prototypes + */ +#if defined (MAPT_UNIFICATION_ENABLED) +static RETURN_STATUS CosaDmlMaptParseResponse (PUCHAR pOptionBuf, UINT16 uiOptionBufLen); +static RETURN_STATUS CosaDmlMaptGetIPv6StringFromHex (PUCHAR pIPv6AddrH, PCHAR pIPv6AddrS); +static RETURN_STATUS CosaDmlMaptConvertStringToHexStream (PUCHAR pOptionBuf, PUINT16 uiOptionBufLen); +/* + * Global definitions + */ +static COSA_DML_MAPT_DATA g_stMaptData; + +/* + * Static function definitions + */ +static RETURN_STATUS +CosaDmlMaptGetIPv6StringFromHex +( + PUCHAR pIPv6AddrH, + PCHAR pIPv6AddrS +) +{ + int rc = -1; + MAPT_LOG_INFO("Entry"); + + if ( !(pIPv6AddrH && pIPv6AddrS) ) + { + MAPT_LOG_ERROR("NULL inputs(%s - %s) for IPv6 hex to string conversion!", + pIPv6AddrH, pIPv6AddrS); + return STATUS_FAILURE; + } + + rc = memset(pIPv6AddrS, 0, BUFLEN_40); + ERR_CHK(rc); + + if ( !inet_ntop(AF_INET6, pIPv6AddrH, pIPv6AddrS, BUFLEN_40) ) + { + MAPT_LOG_ERROR("Invalid IPv6 hex address"); + return STATUS_FAILURE; + } + + return STATUS_SUCCESS; +} + +static RETURN_STATUS +CosaDmlMaptParseResponse +( + PUCHAR pOptionBuf, + UINT16 uiOptionBufLen +) +{ + RETURN_STATUS retStatus = STATUS_SUCCESS; + PCOSA_DML_MAPT_OPTION pStartBuf = NULL; + PCOSA_DML_MAPT_OPTION pNxtOption = NULL; + PCOSA_DML_MAPT_OPTION pEndBuf = NULL; + UINT16 uiOptionLen = 0; + UINT16 uiOption = 0; + PUCHAR pCurOption = 0; + int rc = -1; + + MAPT_LOG_INFO("Entry"); + + if ( !(pOptionBuf && *(pOptionBuf+1)) ) + { + MAPT_LOG_ERROR("MAPT Option-95 Response is NULL !!"); + return STATUS_FAILURE; + } + + pStartBuf = (PCOSA_DML_MAPT_OPTION)pOptionBuf; + pEndBuf = (PCOSA_DML_MAPT_OPTION)((PCHAR)pOptionBuf + uiOptionBufLen); +MAPT_LOG_INFO("<<>> Start : %p | End : %p", pStartBuf,pEndBuf); + for ( ;pStartBuf + 1 <= pEndBuf; pStartBuf = pNxtOption ) + { + uiOptionLen = ntohs(pStartBuf->OptLen); + uiOption = ntohs(pStartBuf->OptType); + + pCurOption = (PUCHAR)(pStartBuf + 1); + pNxtOption = (PCOSA_DML_MAPT_OPTION)(pCurOption + uiOptionLen); + MAPT_LOG_INFO("<<>> Cur : %p | Nxt : %p", pCurOption,pNxtOption); + MAPT_LOG_INFO("<<>> Opt : %u | OpLen : %u", uiOption,uiOptionLen); + + /* option length field overrun */ + if ( pNxtOption > pEndBuf ) + { + MAPT_LOG_ERROR("Malformed MAP options!"); + retStatus = STATUS_FAILURE; //STATUS_BAD_PAYLOAD + break; + } + + switch ( uiOption ) + { + case MAPT_OPTION_S46_RULE: + { + UINT8 bytesLeftOut = 0; + UINT8 v6ByteLen = 0; + UINT8 v6BitLen = 0; + UCHAR v6Addr[BUFLEN_24]; + + g_stMaptData.bFMR = (*pCurOption & 0x01)? TRUE : FALSE; + g_stMaptData.EaLen = *++pCurOption; + g_stMaptData.RuleIPv4PrefixLen = *++pCurOption; + pCurOption++; + + rc = snprintf (g_stMaptData.RuleIPv4Prefix, sizeof(g_stMaptData.RuleIPv4Prefix), + "%d.%d.%d.%d", + pCurOption[0], pCurOption[1], pCurOption[2], pCurOption[3]); + ERR_CHK(rc); + + g_stMaptData.RuleIPv6PrefixLen = *(pCurOption += 4); + v6ByteLen = g_stMaptData.RuleIPv6PrefixLen / 8; + v6BitLen = g_stMaptData.RuleIPv6PrefixLen % 8; + pCurOption++; + + rc = memset (&v6Addr, 0, sizeof(v6Addr)); + ERR_CHK(rc); + rc = memcpy (&v6Addr, pCurOption, (v6ByteLen+(v6BitLen?1:0))*sizeof(CHAR)); + ERR_CHK(rc); + + if ( v6BitLen ) + { + *((PCHAR)&v6Addr + v6ByteLen) &= 0xFF << (8 - v6BitLen); + } + + rc = memcpy (&g_stMaptData.RuleIPv6PrefixH, v6Addr, + (v6ByteLen+(v6BitLen?1:0))*sizeof(CHAR)); + ERR_CHK(rc); + CosaDmlMaptGetIPv6StringFromHex (g_stMaptData.RuleIPv6PrefixH, + g_stMaptData.RuleIPv6Prefix); + MAPT_LOG_INFO("<<>> g_stMaptData.bFMR : %d", g_stMaptData.bFMR); + MAPT_LOG_INFO("<<>> g_stMaptData.EaLen : %u", g_stMaptData.EaLen); + MAPT_LOG_INFO("<<>> g_stMaptData.RuleIPv4PrefixLen : %u", g_stMaptData.RuleIPv4PrefixLen); + MAPT_LOG_INFO("<<>> g_stMaptData.RuleIPv4Prefix : %s", g_stMaptData.RuleIPv4Prefix); + MAPT_LOG_INFO("<<>> g_stMaptData.RuleIPv6PrefixLen : %u", g_stMaptData.RuleIPv6PrefixLen); + MAPT_LOG_INFO("<<>> g_stMaptData.RuleIPv6Prefix : %s", g_stMaptData.RuleIPv6Prefix); + MAPT_LOG_INFO("Parsing OPTION_S46_RULE Successful."); + + /* + * check port parameter option: + * prefix6_len, located at 8th byte in rule option, specifies + * the length of following v6prefix. So the length of port + * param option, if any, must be rule_opt_len minus 8 minus v6ByteLen minus (1 or 0) + */ + bytesLeftOut = uiOptionLen - 8 - v6ByteLen - (v6BitLen?1:0); + + g_stMaptData.Ratio = 1 << (g_stMaptData.EaLen - + (BUFLEN_32 - g_stMaptData.RuleIPv4PrefixLen)); + /* RFC default */ + g_stMaptData.PsidOffset = 6; + MAPT_LOG_INFO("<<>> g_stMaptData.Ratio : %u", g_stMaptData.Ratio); + MAPT_LOG_INFO("<<>> bytesLeftOut : %u", bytesLeftOut); + if ( bytesLeftOut > 0 ) + { + /* this rule option includes port param option */ + if ( bytesLeftOut == 8 ) // Only support one port param option per rule option + { + UINT16 uiSubOptionLen = 0; + UINT16 uiSubOption = 0; + + pCurOption += v6ByteLen + (v6BitLen?1:0); + uiSubOptionLen = ntohs(((PCOSA_DML_MAPT_OPTION)pCurOption)->OptLen); + uiSubOption = ntohs(((PCOSA_DML_MAPT_OPTION)pCurOption)->OptType); + + if ( uiSubOption == MAPT_OPTION_S46_PORT_PARAMS && + uiSubOptionLen == 4 ) + { + g_stMaptData.PsidOffset = (*(pCurOption += uiSubOptionLen))? + *pCurOption:6; + g_stMaptData.PsidLen = *++pCurOption; + + if ( !g_stMaptData.EaLen ) + { + g_stMaptData.Ratio = 1 << g_stMaptData.PsidLen; + } + /* + * RFC 7598: 4.5: 16 bits long. The first k bits on the left of + * this field contain the PSID binary value. The remaining (16 - k) + * bits on the right are padding zeros. + */ + g_stMaptData.Psid = ntohs(*((PUINT16)++pCurOption)) >> + (16 - g_stMaptData.PsidLen); + MAPT_LOG_INFO("<<>> g_stMaptData.Psid : %u", g_stMaptData.Psid); + MAPT_LOG_INFO("<<>> g_stMaptData.PsidLen : %u", g_stMaptData.PsidLen); + MAPT_LOG_INFO("<<>> g_stMaptData.PsidOffset : %u", g_stMaptData.PsidOffset); + MAPT_LOG_INFO("<<>> g_stMaptData.Ratio : %u", g_stMaptData.Ratio); + MAPT_LOG_INFO("Parsing OPTION_S46_PORT_PARAM Successful."); + } + else + { + MAPT_LOG_WARNING("OPTION_S46_PORT_PARAM option length(%d) varies!" + , uiSubOptionLen); + } + } + else + { + MAPT_LOG_WARNING("Port param option length(%d) not equal to 8" + , bytesLeftOut); + } + } + break; + } + + case MAPT_OPTION_S46_BR: + { + MAPT_LOG_WARNING("Parsing OPTION_S46_BR is not supported !"); + //retStatus = STATUS_NOT_SUPPORTED; + break; + } + + case MAPT_OPTION_S46_DMR: + { + UCHAR ipv6Addr[BUFLEN_24]; + + g_stMaptData.BrIPv6PrefixLen = *pCurOption++; + + /* RFC 6052: 2.2: g_stMaptData.BrIPv6PrefixLen%8 must be 0! */ + rc = memset (&ipv6Addr, 0, sizeof(ipv6Addr)); + ERR_CHK(rc); + rc = memcpy (&ipv6Addr, pCurOption, g_stMaptData.BrIPv6PrefixLen/8); + ERR_CHK(rc); + + CosaDmlMaptGetIPv6StringFromHex (ipv6Addr, g_stMaptData.BrIPv6Prefix); + MAPT_LOG_INFO("<<>> g_stMaptData.BrIPv6PrefixLen : %u", g_stMaptData.BrIPv6PrefixLen); + MAPT_LOG_INFO("<<>> g_stMaptData.BrIPv6Prefix : %s", g_stMaptData.BrIPv6Prefix); + MAPT_LOG_INFO("Parsing OPTION_S46_DMR Successful."); + break; + } + + default: + MAPT_LOG_ERROR("Unknown or unexpected MAP option : %d | option len : %d" + , uiOption, uiOptionLen); + //retStatus = STATUS_NOT_SUPPORTED; + break; + } + } + + /* Check a parameter from each mandatory options */ + if ( !g_stMaptData.RuleIPv6PrefixLen || !g_stMaptData.BrIPv6PrefixLen) + { + MAPT_LOG_ERROR("Mandatory mapt options are missing !"); + retStatus = STATUS_FAILURE; + } + + return retStatus; +} + + +static RETURN_STATUS +CosaDmlMaptConvertStringToHexStream +( + PUCHAR pWriteBf, + PUINT16 uiOptionBufLen +) +{ + PUCHAR pReadBf = pWriteBf; + MAPT_LOG_INFO("Entry"); + + if ( !pWriteBf ) + { + MAPT_LOG_ERROR("MAPT string buffer is empty !!"); + return STATUS_FAILURE; + } + + if ( *pReadBf == '\'' && pReadBf++ ) {} + + if ( pReadBf[strlen((PCHAR)pReadBf)-1] == '\'' ) + { + pReadBf[strlen((PCHAR)pReadBf)-1] = '\0'; + } + + MAPT_LOG_INFO("<<>> pOptionBuf is %p : %s",pReadBf, pReadBf); + while ( *pReadBf && *(pReadBf+1) ) + { + if ( *pReadBf == ':' && pReadBf++ ) {} + + *pWriteBf = (STRING_TO_HEX(*pReadBf) << 4) | STRING_TO_HEX(*(pReadBf+1)); + + ++pWriteBf; + ++pReadBf; + ++pReadBf; + ++*uiOptionBufLen; + } + *pWriteBf = '\0'; + MAPT_LOG_INFO("<<>> BufLen : %d", *uiOptionBufLen); + + return STATUS_SUCCESS; +} + +/** + * @brief Parses the MAPT option 95 response. + * + * This function processes the MAPT option 95 response, extracts the relevant information and updates ipc_dhcpv6_data_t struct with mapt details + * + * @param[in] pPdIPv6Prefix Pointer to the IPv6 prefix. + * @param[in] pOptionBuf Pointer to the buffer containing the option 95 data. + * @param[out] dhcpv6_data Pointer to the structure where the parsed DHCPv6 data will be stored. + * + * @return ANSC_STATUS indicating the success or failure of the operation. + */ + +ANSC_STATUS WanMgr_MaptParseOpt95Response +( + PCHAR pPdIPv6Prefix, + PUCHAR pOptionBuf, + ipc_dhcpv6_data_t *dhcpv6_data +) +{ + RETURN_STATUS ret = STATUS_SUCCESS; + UINT16 uiOptionBufLen = 0; + int rc = -1; + + MAPT_LOG_INFO("Entry"); + + /* Convert the received string buffer into hex stream */ + rc = memset (&g_stMaptData, 0, sizeof(g_stMaptData)); + ERR_CHK(rc); + if ( CosaDmlMaptConvertStringToHexStream (pOptionBuf, &uiOptionBufLen) != STATUS_SUCCESS ) + { + MAPT_LOG_ERROR("MAPT string buffer to HexStream conversion Failed !!"); + ret = STATUS_FAILURE; + } + + /* Store IPv6 prefix and length */ + rc = memcpy (&g_stMaptData.PdIPv6Prefix, pPdIPv6Prefix, + (strchr(pPdIPv6Prefix, '/') - pPdIPv6Prefix)); + ERR_CHK(rc); + g_stMaptData.PdIPv6PrefixLen = strtol((strchr(pPdIPv6Prefix, '/') + 1), NULL, 10); + MAPT_LOG_INFO("<<>> Received PdIPv6Prefix : %s/%u", g_stMaptData.PdIPv6Prefix + , g_stMaptData.PdIPv6PrefixLen); + if ( !ret && !g_stMaptData.PdIPv6Prefix[0] ) + { + MAPT_LOG_ERROR("PdIPv6Prefix is NULL !!"); + ret = STATUS_FAILURE; + } + + /* Parse the hex buffer for mapt options */ + if ( !ret && CosaDmlMaptParseResponse (pOptionBuf, uiOptionBufLen) != STATUS_SUCCESS ) + { + MAPT_LOG_ERROR("MAPT Parsing Response Failed !!"); + ret = STATUS_FAILURE; + } + + if( ret == STATUS_SUCCESS ) + { + //Fill Required MAP-T information + dhcpv6_data->maptAssigned = TRUE; + dhcpv6_data->mapt.v6Len = g_stMaptData.RuleIPv6PrefixLen; + dhcpv6_data->mapt.isFMR = g_stMaptData.bFMR ? TRUE : FALSE; + dhcpv6_data->mapt.eaLen = g_stMaptData.EaLen; + dhcpv6_data->mapt.v4Len = g_stMaptData.RuleIPv4PrefixLen; + dhcpv6_data->mapt.psidOffset = g_stMaptData.PsidOffset; + dhcpv6_data->mapt.psidLen = g_stMaptData.PsidLen; + dhcpv6_data->mapt.psid = g_stMaptData.Psid; + dhcpv6_data->mapt.iapdPrefixLen = g_stMaptData.PdIPv6PrefixLen; + dhcpv6_data->mapt.ratio = g_stMaptData.Ratio; + + rc = snprintf (dhcpv6_data->mapt.pdIPv6Prefix, BUFLEN_40, "%s", g_stMaptData.PdIPv6Prefix); + ERR_CHK(rc); + rc = snprintf (dhcpv6_data->mapt.ruleIPv4Prefix, BUFLEN_40, "%s", g_stMaptData.RuleIPv4Prefix); + ERR_CHK(rc); + rc = snprintf (dhcpv6_data->mapt.ruleIPv6Prefix, BUFLEN_40, "%s/%u", g_stMaptData.RuleIPv6Prefix + , g_stMaptData.RuleIPv6PrefixLen); + ERR_CHK(rc); + rc = snprintf (dhcpv6_data->mapt.brIPv6Prefix, BUFLEN_40, "%s/%u", g_stMaptData.BrIPv6Prefix + , g_stMaptData.BrIPv6PrefixLen); + ERR_CHK(rc); + + MAPT_LOG_INFO("MAPT configuration complete.\n"); + } + + return ((ret) ? ANSC_STATUS_FAILURE : ANSC_STATUS_SUCCESS); +} + +#endif // MAPT_UNIFICATION_ENABLED + +int remove_single_quote (char *buf) +{ + int i = 0; + int j = 0; + + while (buf[i] != '\0' && i < 255) { + if (buf[i] != '\'') { + buf[j++] = buf[i]; + } + i++; + } + buf[j] = '\0'; + return 0; +} + +typedef struct +{ + char* value; // Pointer to the IANA/IAPD value etc.. + char* eventName; // Corresponding event name +} Ipv6SyseventMap; + +/* processIpv6LeaseSysevents() + * This funtion is used to set the IPv6 lease related sysevents + */ +void processIpv6LeaseSysevents(Ipv6SyseventMap* eventMaps, size_t size, const char* IfaceName) +{ + + // Loop through the eventMaps array + for (size_t i = 0; i < size; i++) + { + if (eventMaps[i].value[0] != '\0' && strcmp(eventMaps[i].value, "\'\'") != 0) + { + char sysEventName[256] = {0}; + remove_single_quote(eventMaps[i].value); + snprintf(sysEventName, sizeof(sysEventName), eventMaps[i].eventName, IfaceName); + CcspTraceInfo(("%s - %d: Setting sysevent %s to %s \n", __FUNCTION__, __LINE__, sysEventName, eventMaps[i].value)); + sysevent_set(sysevent_fd, sysevent_token, sysEventName, eventMaps[i].value, 0); + } + } +} + +/* This thread is used to parse the Ipv6 lease iformation sent by the DHCPv6 clients and sends the information to WanManager. + * + */ +static void * WanMgr_DhcpV6MsgHandler() +{ + int fd=0 ; + char msg[1024]; + char * p = NULL; + + CcspTraceInfo(("%s - %d: created (WanManager Unified Version) ", __FUNCTION__, __LINE__)); + + fd_set rfds; + struct timeval tm; + fd= open(CCSP_COMMON_FIFO, O_RDWR); + if (fd< 0) + { + CcspTraceError(("%s - %d: open common fifo!!!!!!!!!!!! : %s . Exit thread", __FUNCTION__, __LINE__, strerror(errno))); + pthread_exit(NULL); + } + while (1) + { + int retCode = 0; + tm.tv_sec = 60; + tm.tv_usec = 0; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + retCode = select(fd+1, &rfds, NULL, NULL, &tm); + /* When return -1, it's error. + When return 0, it's timeout + When return >0, it's the number of valid fds */ + if (retCode < 0) { + fprintf(stderr, "dbg_thrd : select returns error \n" ); + if (errno == EINTR) + continue; + + CcspTraceWarning(("%s -- select(): %s. Exit thread", __FUNCTION__, strerror(errno))); + pthread_exit(NULL); + } + else if(retCode == 0 ) + continue; + + if ( FD_ISSET(fd, &rfds) ) + { + ssize_t msg_len = 0; + msg[0] = 0; + msg_len = read(fd, msg, sizeof(msg)-1); + if(msg_len > 0) + msg[msg_len] = 0; + } + else + continue; + + if (msg[0] != 0) + { + CcspTraceInfo(("%s: get message %s\n", __func__, msg)); + } else { + //Message is empty. Wait 5 sec before trying the select again. + sleep(5); + continue; + } + + if (!strncmp(msg, "dibbler-client", strlen("dibbler-client"))) + { + //Interface name + char IfaceName[64] = {0}; + //Action (add or delete) + char action[64] = {0}; + //IANA related varibales + char v6addr[64] = {0}, iana_t1[32] = {0}, iana_t2[32] = {0}, iana_iaid[32] = {0}, iana_pretm[32] = {0}, iana_vldtm[32] = {0}; + //IAPD related varibales + char v6pref[128] = {0}, preflen[12] = {0}, iapd_t1[32] = {0}, iapd_t2[32] = {0}, iapd_iaid[32] = {0}, iapd_pretm[32] = {0}, iapd_vldtm[32] = {0}; + int pref_len = 0; + + p = msg+strlen("dibbler-client"); + while(isblank(*p)) p++; + fprintf(stderr, "%s -- %d !!! get event from v6 client: %s \n", __FUNCTION__, __LINE__,p); +#if defined (MAPT_UNIFICATION_ENABLED) + unsigned char opt95_dBuf[BUFLEN_256] = {0}; + int dataLen = sscanf(p, "%63s %63s %63s %31s %31s %31s %31s %31s %63s %11s %31s %31s %31s %31s %31s %255s", + action, IfaceName, v6addr, iana_iaid, iana_t1, iana_t2, iana_pretm, iana_vldtm, + v6pref, preflen, iapd_iaid, iapd_t1, iapd_t2, iapd_pretm, iapd_vldtm, + opt95_dBuf); + CcspTraceDebug(("%s,%d: dataLen = %d\n", __FUNCTION__, __LINE__, dataLen)); + if (dataLen == 16) +#else // MAPT_UNIFICATION_ENABLED + int dataLen = sscanf(p, "%63s %63s %63s %31s %31s %31s %31s %31s %63s %11s %31s %31s %31s %31s %31s", + action, IfaceName, v6addr, iana_iaid, iana_t1, iana_t2, iana_pretm, iana_vldtm, + v6pref, preflen, iapd_iaid, iapd_t1, iapd_t2, iapd_pretm, iapd_vldtm); + if (dataLen == 15) +#endif + { + remove_single_quote(v6addr); + remove_single_quote(v6pref); + remove_single_quote(preflen); + remove_single_quote(IfaceName); + pref_len = atoi(preflen); + CcspTraceDebug(("%s,%d: v6addr=%s, v6pref=%s, pref_len=%d\n", __FUNCTION__, __LINE__, v6addr, v6pref, pref_len)); + + if (!strncmp(action, "add", 3)) + { + CcspTraceInfo(("%s: add\n", __func__)); + //TODO : Waiting until private lan interface is ready ? + // Waiting until private lan interface is ready , so that we can assign global ipv6 address and also start dhcp server. + + ipc_dhcpv6_data_t dhcpv6_data; + memset(&dhcpv6_data, 0, sizeof(ipc_dhcpv6_data_t)); + strncpy(dhcpv6_data.ifname, IfaceName, sizeof(dhcpv6_data.ifname)); + if(strlen(v6pref) == 0 && strlen(v6addr) ==0) + { + dhcpv6_data.isExpired = TRUE; + } else + { + dhcpv6_data.isExpired = FALSE; + //Reset MAP flags + dhcpv6_data.maptAssigned = FALSE; + dhcpv6_data.mapeAssigned = FALSE; + if(strlen(v6pref) > 0 && strncmp(v6pref, "\\0",2)!=0) + { + CcspTraceInfo(("%s %d Prefix Assigned\n", __FUNCTION__, __LINE__)); + snprintf(dhcpv6_data.sitePrefix, sizeof(dhcpv6_data.sitePrefix), "%s/%d", v6pref, pref_len); + + dhcpv6_data.prefixAssigned = TRUE; + strncpy(dhcpv6_data.pdIfAddress, "", sizeof(dhcpv6_data.pdIfAddress)); + dhcpv6_data.prefixCmd = 0; + remove_single_quote(iapd_pretm); + remove_single_quote(iapd_vldtm); + sscanf(iapd_pretm, "%d", &(dhcpv6_data.prefixPltime)); + sscanf(iapd_vldtm, "%d", &(dhcpv6_data.prefixVltime)); + + //IPv6 prefix related sysevents + // Define the eventMaps array as before + Ipv6SyseventMap eventMaps[] = { + {dhcpv6_data.sitePrefix, COSA_DML_WANIface_PREF_SYSEVENT_NAME}, + {iapd_iaid, COSA_DML_WANIface_PREF_IAID_SYSEVENT_NAME}, + {iapd_t1, COSA_DML_WANIface_PREF_T1_SYSEVENT_NAME}, + {iapd_t2, COSA_DML_WANIface_PREF_T2_SYSEVENT_NAME}, + {iapd_pretm,COSA_DML_WANIface_PREF_PRETM_SYSEVENT_NAME}, + {iapd_vldtm,COSA_DML_WANIface_PREF_VLDTM_SYSEVENT_NAME} + }; + /* Set Interface specific sysevnts. This is used for Ip interface DM */ + processIpv6LeaseSysevents(eventMaps, sizeof(eventMaps) / sizeof(eventMaps[0]), IfaceName); + +#if defined (MAPT_UNIFICATION_ENABLED) + if (opt95_dBuf[0] == '\0' || strlen((char*)opt95_dBuf) <=0 || strcmp((char*)opt95_dBuf, "\'\'") == 0) + { + CcspTraceInfo(("%s: MAP-T configuration not available.\n", __FUNCTION__)); + } + else + { + WanMgr_MaptParseOpt95Response(dhcpv6_data.sitePrefix, opt95_dBuf, &dhcpv6_data); + } +#endif // MAPT_UNIFICATION_ENABLED + } + + if(strlen(v6addr) > 0 && strncmp(v6addr, "\\0",2)!=0) + { + CcspTraceInfo(("%s %d Addr Assigned\n", __FUNCTION__, __LINE__)); + dhcpv6_data.addrAssigned = TRUE; + strncpy(dhcpv6_data.address, v6addr, sizeof(dhcpv6_data.address)-1); + dhcpv6_data.addrCmd = 0; + + //IPv6 IANA related sysevents + // Define the eventMaps array as before + Ipv6SyseventMap eventMaps[] = { + {v6addr, COSA_DML_WANIface_ADDR_SYSEVENT_NAME}, + {iana_iaid, COSA_DML_WANIface_ADDR_IAID_SYSEVENT_NAME}, + {iana_t1, COSA_DML_WANIface_ADDR_T1_SYSEVENT_NAME}, + {iana_t2, COSA_DML_WANIface_ADDR_T2_SYSEVENT_NAME}, + {iana_pretm,COSA_DML_WANIface_ADDR_PRETM_SYSEVENT_NAME}, + {iana_vldtm,COSA_DML_WANIface_ADDR_VLDTM_SYSEVENT_NAME}, + }; + + /* Set Interface specific sysevnts. This is used for Ip interface DM */ + processIpv6LeaseSysevents(eventMaps, sizeof(eventMaps) / sizeof(eventMaps[0]), IfaceName); + } + + /** DNS servers. **/ + char dns_server[256] = {'\0'}; + //DNS server details are shared using sysvent, it is not part of the dibbler fifo + sysevent_get(sysevent_fd, sysevent_token, "ipv6_nameserver", dns_server, sizeof(dns_server)); + if (strlen(dns_server) != 0) + { + dhcpv6_data.dnsAssigned = TRUE; + sscanf (dns_server, "%s %s", dhcpv6_data.nameserver, dhcpv6_data.nameserver1); + } + } + + //get iface data + DML_VIRTUAL_IFACE* pVirtIf = WanMgr_GetVIfByName_VISM_running_locked(dhcpv6_data.ifname); + if(pVirtIf != NULL) + { + //check if previously message was already handled + if(pVirtIf->IP.pIpcIpv6Data == NULL) + { + //allocate + pVirtIf->IP.pIpcIpv6Data = (ipc_dhcpv6_data_t*) malloc(sizeof(ipc_dhcpv6_data_t)); + if(pVirtIf->IP.pIpcIpv6Data != NULL) + { + // copy data + memcpy(pVirtIf->IP.pIpcIpv6Data, &dhcpv6_data, sizeof(ipc_dhcpv6_data_t)); + CcspTraceInfo(("%s %d IPv6 lease info add to Interface ID(%d), Virtual interface Name : %s , Alias %s \n", __FUNCTION__, __LINE__, pVirtIf->baseIfIdx+1, pVirtIf->Name, pVirtIf->Alias)); + } + } + //release lock + WanMgr_VirtualIfaceData_release(pVirtIf); + } + + + } + else if (!strncmp(action, "del", 3)) + { + /*todo*/ + } + } + } + } + if(fd>=0) { + close(fd); + } + return NULL; +} + +ANSC_STATUS WanMgr_DhcpV6MsgHandlerInit() +{ + ANSC_STATUS retStatus = ANSC_STATUS_FAILURE; + int ret = -1; + + //create thread + pthread_t ipv6LeaseParser; + if ( ( !mkfifo(CCSP_COMMON_FIFO, 0666) || errno == EEXIST ) ) + { + ret = pthread_create( &ipv6LeaseParser, NULL, &WanMgr_DhcpV6MsgHandler, NULL ); + + if( 0 != ret ) + { + CcspTraceError(("%s %d - Failed to start WanMgr_DhcpV6MsgHandler Thread Error:%d\n", __FUNCTION__, __LINE__, ret)); + } + else + { + CcspTraceInfo(("%s %d - WanMgr_DhcpV6MsgHandler Thread Started Successfully\n", __FUNCTION__, __LINE__)); + retStatus = ANSC_STATUS_SUCCESS; + } + } + else + { + CcspTraceError(("%s %d - Failed to create %s \n", __FUNCTION__, __LINE__, CCSP_COMMON_FIFO)); + } + return retStatus ; +} + + diff --git a/source/WanManager/DHCPv6cMsgHandler/dhcpv6c_msg_apis.h b/source/WanManager/DHCPv6cMsgHandler/dhcpv6c_msg_apis.h new file mode 100644 index 0000000..6528609 --- /dev/null +++ b/source/WanManager/DHCPv6cMsgHandler/dhcpv6c_msg_apis.h @@ -0,0 +1,230 @@ +/* + * If not stated otherwise in this file or this component's Licenses.txt file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/********************************************************************** + Copyright [2014] [Cisco Systems, Inc.] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +**********************************************************************/ + +#ifndef _DHCPV6_MSG_APIS_H +#define _DHCPV6_MSG_APIS_H + + +#include "ipc_msg.h" + +/* + * DHCP MAPT options macro definitions + */ +#define MAPT_OPTION_S46_RULE 89 +#define MAPT_OPTION_S46_BR 90 +#define MAPT_OPTION_S46_DMR 91 +#define MAPT_OPTION_S46_PORT_PARAMS 93 +#define MAPT_OPTION_S46_CONT_MAPT 95 + +#define BUFLEN_4 4 +#define BUFLEN_8 8 +#define BUFLEN_16 16 +#define BUFLEN_24 24 +#define BUFLEN_32 32 +#define BUFLEN_40 40 +#define BUFLEN_64 64 +#define BUFLEN_128 128 +#define BUFLEN_256 256 +#define BUFLEN_512 512 +#define BUFLEN_1024 1024 + +/* + * Data type Macro definitions + */ +#ifndef VOID + #define VOID void +#endif + +#ifndef UINT8 + #define UINT8 unsigned char +#endif + +#ifndef UINT16 + #define UINT16 unsigned short +#endif + +#ifndef UINT32 + #define UINT32 unsigned int +#endif + +#ifndef UCHAR + #define UCHAR unsigned char +#endif + +#ifndef ULONG + #define ULONG unsigned long +#endif + +#ifndef ULONGLONG + #define ULONGLONG unsigned long long +#endif + +#ifndef CHAR + #define CHAR char +#endif + +#ifndef INT8 + #define INT8 char +#endif + +#ifndef INT16 + #define INT16 short +#endif + +#ifndef INT32 + #define INT32 int +#endif + +#ifndef LONG + #define LONG long +#endif + +#ifndef PVOID + #define PVOID void* +#endif + +#ifndef PCHAR + #define PCHAR char* +#endif + +#ifndef PUCHAR + #define PUCHAR unsigned char* +#endif + +#ifndef PUINT8 + #define PUINT8 unsigned char* +#endif + +#ifndef PUINT16 + #define PUINT16 unsigned short* +#endif + +#ifndef PUINT32 + #define PUINT32 unsigned int* +#endif + +#ifndef PULONG + #define PULONG unsigned long* +#endif + +#ifndef BOOLEAN + #define BOOLEAN unsigned char +#endif + +#define MAPT_LOG_INFO(format, ...) \ + CcspTraceInfo (("%s - "format"\n", __FUNCTION__, ##__VA_ARGS__)) +#define MAPT_LOG_ERROR(format, ...) \ + CcspTraceError (("%s - "format"\n", __FUNCTION__, ##__VA_ARGS__)) +#define MAPT_LOG_NOTICE(format, ...) \ + CcspTraceNotice (("%s - "format"\n", __FUNCTION__, ##__VA_ARGS__)) +#define MAPT_LOG_WARNING(format, ...) \ + CcspTraceWarning(("%s - "format"\n", __FUNCTION__, ##__VA_ARGS__)) + +#define COSA_DML_WANIface_PREF_SYSEVENT_NAME "tr_%s_dhcpv6_client_v6pref" +#define COSA_DML_WANIface_PREF_IAID_SYSEVENT_NAME "tr_%s_dhcpv6_client_pref_iaid" +#define COSA_DML_WANIface_PREF_T1_SYSEVENT_NAME "tr_%s_dhcpv6_client_pref_t1" +#define COSA_DML_WANIface_PREF_T2_SYSEVENT_NAME "tr_%s_dhcpv6_client_pref_t2" +#define COSA_DML_WANIface_PREF_PRETM_SYSEVENT_NAME "tr_%s_dhcpv6_client_pref_pretm" +#define COSA_DML_WANIface_PREF_VLDTM_SYSEVENT_NAME "tr_%s_dhcpv6_client_pref_vldtm" + +#define COSA_DML_WANIface_ADDR_SYSEVENT_NAME "tr_%s_dhcpv6_client_v6addr" +#define COSA_DML_WANIface_ADDR_IAID_SYSEVENT_NAME "tr_%s_dhcpv6_client_addr_iaid" +#define COSA_DML_WANIface_ADDR_T1_SYSEVENT_NAME "tr_%s_dhcpv6_client_addr_t1" +#define COSA_DML_WANIface_ADDR_T2_SYSEVENT_NAME "tr_%s_dhcpv6_client_addr_t2" +#define COSA_DML_WANIface_ADDR_PRETM_SYSEVENT_NAME "tr_%s_dhcpv6_client_addr_pretm" +#define COSA_DML_WANIface_ADDR_VLDTM_SYSEVENT_NAME "tr_%s_dhcpv6_client_addr_vldtm" + +/* + * Enums and structure definition + */ +typedef enum +_RETURN_STATUS +{ + STATUS_SUCCESS = 0, + STATUS_FAILURE = -1 +} RETURN_STATUS; + +typedef struct +_COSA_DML_MAPT_DATA +{ + CHAR RuleIPv4Prefix[BUFLEN_16]; + CHAR RuleIPv6Prefix[BUFLEN_40]; + CHAR IPv4AddrString[BUFLEN_16]; + CHAR IPv6AddrString[BUFLEN_40]; + CHAR PdIPv6Prefix[BUFLEN_40]; + CHAR BrIPv6Prefix[BUFLEN_40]; + UCHAR RuleIPv6PrefixH[BUFLEN_24]; + UINT16 RuleIPv4PrefixLen; + UINT16 RuleIPv6PrefixLen; + UINT16 BrIPv6PrefixLen; + UINT16 PdIPv6PrefixLen; + UINT16 EaLen; + UINT16 Psid; + UINT16 PsidLen; + UINT32 PsidOffset; + UINT32 IPv4Suffix; + UINT16 IPv4Psid; + UINT16 IPv4PsidLen; + UINT32 Ratio; + BOOLEAN bFMR; +} COSA_DML_MAPT_DATA, *PCOSA_DML_MAPT_DATA; + + +typedef struct +_COSA_DML_MAPT_OPTION +{ + UINT16 OptType; + UINT16 OptLen; +} __attribute__ ((__packed__)) COSA_DML_MAPT_OPTION, *PCOSA_DML_MAPT_OPTION; + +/** + * @brief Parses the MAPT option 95 response. + * + * This function processes the MAPT option 95 response, extracts the relevant information and updates ipc_dhcpv6_data_t struct with mapt details + * + * @param[in] pPdIPv6Prefix Pointer to the IPv6 prefix. + * @param[in] pOptionBuf Pointer to the buffer containing the option 95 data. + * @param[out] dhcpv6_data Pointer to the structure where the parsed DHCPv6 data will be stored. + * + * @return ANSC_STATUS indicating the success or failure of the operation. + */ + +ANSC_STATUS WanMgr_MaptParseOpt95Response + ( + PCHAR pPdIPv6Prefix, + PUCHAR pOptionBuf, + ipc_dhcpv6_data_t *dhcpv6_data + ); +#endif diff --git a/source/WanManager/Makefile.am b/source/WanManager/Makefile.am index ec96f1c..a9d516e 100644 --- a/source/WanManager/Makefile.am +++ b/source/WanManager/Makefile.am @@ -25,9 +25,16 @@ wanmanager_DEPENDENCIES = \ wanmanager_CPPFLAGS = -I$(top_srcdir)/source/TR-181/middle_layer_src \ -I$(top_srcdir)/source/TR-181/include \ + -I$(top_srcdir)/source/WanManager/MaptParsing \ -I${PKG_CONFIG_SYSROOT_DIR}$(includedir)/rbus wanmanager_CFLAGS = -DFEATURE_SUPPORT_RDKLOG $(DBUS_CFLAGS) $(SYSTEMD_CFLAGS) wanmanager_CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" wanmanager_SOURCES = wanmgr_webconfig_apis.c wanmgr_webconfig.c wanmgr_main.c wanmgr_ssp_action.c wanmgr_ssp_messagebus_interface.c wanmgr_core.c wanmgr_controller.c wanmgr_data.c wanmgr_sysevents.c wanmgr_interface_sm.c wanmgr_utils.c wanmgr_net_utils.c wanmgr_dhcpv4_apis.c wanmgr_dhcpv6_apis.c wanmgr_ipc.c wanmgr_dhcpv4_internal.c wanmgr_dhcpv6_internal.c wanmgr_policy_autowan_impl.c wanmgr_policy_auto_impl.c dm_pack_datamodel.c wanmgr_wan_failover.c wanmgr_policy_parallel_scan_impl.c wanmgr_dhcp_legacy_apis.c wanmanager_LDADD = $(wanmanager_DEPENDENCIES) -lccsp_common -lrdkloggers $(DBUS_LIBS) $(SYSTEMD_LDFLAGS) -lhal_platform -lapi_dhcpv4c -lnanomsg -lwebconfig_framework -lmsgpackc -ldhcp_client_utils -lprivilege -lrbus -lsecure_wrapper + + +if WAN_UNIFICATION_ENABLED +wanmanager_SOURCES += DHCPv6cMsgHandler/dhcpv6c_msg_apis.c +endif + diff --git a/source/WanManager/wanmgr_data.c b/source/WanManager/wanmgr_data.c index 4ff87e9..592889f 100644 --- a/source/WanManager/wanmgr_data.c +++ b/source/WanManager/wanmgr_data.c @@ -455,7 +455,21 @@ WanMgr_Iface_Data_t* WanMgr_GetIfaceDataByName_locked(char* iface_name) return NULL; } -DML_VIRTUAL_IFACE* WanMgr_GetVirtualIfaceByName_locked(char* iface_name) +/** + * @brief Retrieve a virtual interface object by its name with mutex locked state. + * + * This function searches all Virtual Interfaces for and returns a pointer to a virtual interface object + * identified by its name (`iface_name`). + * + * @param[in] iface_name The name of the virtual interface to retrieve. + * This should be a valid, null-terminated string. + * + * @return DML_VIRTUAL_IFACE* + * Pointer to the corresponding virtual interface structure if found, + * or NULL if not found. + */ + +DML_VIRTUAL_IFACE* WanMgr_GetVirtualIfaceByName_locked(const char* iface_name) { UINT idx; if(iface_name == NULL || strlen(iface_name) <=0) @@ -488,6 +502,55 @@ DML_VIRTUAL_IFACE* WanMgr_GetVirtualIfaceByName_locked(char* iface_name) return NULL; } +/** + * @brief Get a virtual interface by its name, ensuring the state machine is running and mutex is locked. + * + * This function searches all virtual interfaces and returns a pointer to the one matching the given name (`iface_name`), + * with the virtual interface state machine (VISM) is running. + * + * NOTE: This function is similar to WanMgr_GetVirtualIfaceByName_locked but includes an additional check to ensure + * the VISM is running. Some products use the same default name for all interfaces, causing issues with lease updates. + * This function serves as a workaround to retrieve the correct interface with an active VISM. + * + * @param[in] iface_name The name of the virtual interface to retrieve (a valid, null-terminated string). + * + * @return DML_VIRTUAL_IFACE* + * Pointer to the corresponding virtual interface if found, + * or NULL if no matching interface is found. + */ +DML_VIRTUAL_IFACE* WanMgr_GetVIfByName_VISM_running_locked(const char* iface_name) +{ + UINT idx; + if(iface_name == NULL || strlen(iface_name) <=0) + { + return NULL; + } + + if(pthread_mutex_lock(&gWanMgrDataBase.gDataMutex) == 0) + { + WanMgr_IfaceCtrl_Data_t* pWanIfaceCtrl = &(gWanMgrDataBase.IfaceCtrl); + if(pWanIfaceCtrl->pIface != NULL) + { + for(idx = 0; idx < pWanIfaceCtrl->ulTotalNumbWanInterfaces; idx++) + { + WanMgr_Iface_Data_t* pWanIfaceData = &(pWanIfaceCtrl->pIface[idx]); + DML_VIRTUAL_IFACE* virIface = pWanIfaceData->data.VirtIfList; + while(virIface != NULL) + { + if(!strcmp(iface_name,virIface->Name) && virIface->Interface_SM_Running == TRUE) + { + return virIface; + } + virIface = virIface->next; + } + } + } + WanMgrDml_GetIfaceData_release(NULL); + } + + return NULL; +} + ANSC_STATUS WanMgr_AddVirtVlanIfToList(DML_VLAN_IFACE_TABLE** head, DML_VLAN_IFACE_TABLE *newNode) { if(NULL == newNode) @@ -761,7 +824,6 @@ void WanMgr_VirtIface_Init(DML_VIRTUAL_IFACE * pVirtIf, UINT iface_index) pVirtIf->EnableMAPT = FALSE; pVirtIf->EnableDSLite = FALSE; pVirtIf->IP.RefreshDHCP = FALSE; // RefreshDHCP is set when there is a change in IP source - pVirtIf->IP.RestartV6Client = FALSE; pVirtIf->Status = WAN_IFACE_STATUS_DISABLED; pVirtIf->RemoteStatus = WAN_IFACE_STATUS_DISABLED; pVirtIf->VLAN.Status = WAN_IFACE_LINKSTATUS_DOWN; diff --git a/source/WanManager/wanmgr_data.h b/source/WanManager/wanmgr_data.h index 4db35ac..9328723 100644 --- a/source/WanManager/wanmgr_data.h +++ b/source/WanManager/wanmgr_data.h @@ -44,7 +44,8 @@ WanMgr_Iface_Data_t* WanMgr_GetIfaceData_locked(UINT iface_index); DML_VIRTUAL_IFACE* WanMgr_getVirtualIface_locked(UINT baseIfidx, UINT virtIfIdx); void WanMgr_VirtualIfaceData_release(DML_VIRTUAL_IFACE* pVirtIf); WanMgr_Iface_Data_t* WanMgr_GetIfaceDataByName_locked(char* iface_name); -DML_VIRTUAL_IFACE* WanMgr_GetVirtualIfaceByName_locked(char* iface_name); +DML_VIRTUAL_IFACE* WanMgr_GetVirtualIfaceByName_locked(const char* iface_name); +DML_VIRTUAL_IFACE* WanMgr_GetVIfByName_VISM_running_locked(const char* iface_name); void WanMgrDml_GetIfaceData_release(WanMgr_Iface_Data_t* pWanIfaceData); void WanMgr_IfaceData_Init(WanMgr_Iface_Data_t* pIfaceData, UINT uiInstNumber); ANSC_STATUS WanMgr_WanDataInit(void); diff --git a/source/WanManager/wanmgr_dhcpv4_apis.c b/source/WanManager/wanmgr_dhcpv4_apis.c index c45286b..e0cad3a 100644 --- a/source/WanManager/wanmgr_dhcpv4_apis.c +++ b/source/WanManager/wanmgr_dhcpv4_apis.c @@ -124,7 +124,8 @@ ANSC_STATUS wanmgr_handle_dhcpv4_event_data(DML_VIRTUAL_IFACE* pVirtIf) bool IPv4ConfigChanged = FALSE; - if( strcmp(pDhcpcInfo->gateway, "0.0.0.0") == 0){ + if( strcmp(pDhcpcInfo->gateway, "0.0.0.0") == 0) + { CcspTraceInfo(("%s %d - gateway=[%s] Iface Status to VALID\n", __FUNCTION__, __LINE__, pDhcpcInfo->gateway)); if (pVirtIf->IP.pIpcIpv4Data != NULL ) { @@ -132,7 +133,13 @@ ANSC_STATUS wanmgr_handle_dhcpv4_event_data(DML_VIRTUAL_IFACE* pVirtIf) free(pVirtIf->IP.pIpcIpv4Data); pVirtIf->IP.pIpcIpv4Data = NULL; } - pVirtIf->Status = WAN_IFACE_STATUS_VALID; + + //Don't set the status to VALID if it is already UP or STANDBY + if(pVirtIf->Status != WAN_IFACE_STATUS_STANDBY && pVirtIf->Status != WAN_IFACE_STATUS_UP) + { + CcspTraceInfo(("%s %d - Setting Iface Status to VALID\n", __FUNCTION__, __LINE__, pDhcpcInfo->gateway)); + pVirtIf->Status = WAN_IFACE_STATUS_VALID; + } return ANSC_STATUS_SUCCESS; } @@ -214,8 +221,7 @@ ANSC_STATUS wanmgr_handle_dhcpv4_event_data(DML_VIRTUAL_IFACE* pVirtIf) // update current IPv4 data wanmgr_dchpv4_get_ipc_msg_info(&(pVirtIf->IP.Ipv4Data), pDhcpcInfo); - - pVirtIf->IP.Ipv4Data.leaseReceivedTime = up_time; + pVirtIf->IP.Ipv4Data.leaseReceivedTime = up_time; /* Assign the address to the inetrface when received. Remaining configurations are updated when activated from VISM*/ CcspTraceInfo(("%s %d - Received Ipv4 lease for interface %s. Configuring address on interface\n", __FUNCTION__, __LINE__, pVirtIf->IP.Ipv4Data.ifname)); @@ -937,6 +943,7 @@ WanMgr_DmlDhcpcGetInfo pInfo->IPRouters[0].Value = inet_addr(p_VirtIf->IP.Ipv4Data.gateway); pInfo->DNSServers[0].Value = inet_addr(p_VirtIf->IP.Ipv4Data.dnsServer); pInfo->DNSServers[1].Value = inet_addr(p_VirtIf->IP.Ipv4Data.dnsServer1); + pInfo->DHCPServer.Value = inet_addr(p_VirtIf->IP.Ipv4Data.dhcpServerId); pInfo->DHCPStatus = ((strcmp(p_VirtIf->IP.Ipv4Data.dhcpState, DHCP_STATE_BOUND) == 0) || (strcmp(p_VirtIf->IP.Ipv4Data.dhcpState, DHCP_STATE_RENEW) == 0)) ? DML_DHCPC_STATUS_Bound : DML_DHCPC_STATUS_Init; diff --git a/source/WanManager/wanmgr_dhcpv6_apis.c b/source/WanManager/wanmgr_dhcpv6_apis.c index 120b3a6..6115d51 100644 --- a/source/WanManager/wanmgr_dhcpv6_apis.c +++ b/source/WanManager/wanmgr_dhcpv6_apis.c @@ -63,6 +63,7 @@ extern char g_Subsystem[32]; #endif #if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) +#define COSA_DML_WANIface_ADDR_SYSEVENT_NAME "tr_%s_dhcpv6_client_v6addr" char PreviousIPv6Address[128] = {0}; //Global varibale to store previous IPv6 address #endif @@ -1586,6 +1587,34 @@ static ANSC_STATUS wanmgr_dchpv6_get_ipc_msg_info(WANMGR_IPV6_DATA* pDhcpv6Data, return ANSC_STATUS_SUCCESS; } +#if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) +/** + * @brief Copies the previous prefix from the old IPv6 data to the new IPv6 data. + * + * This function handles the copying of IAPD details from the old data structure + * to the new one, ensuring that the previous IAPD details are used if only IANA is renewed. + * + * @param[in] pOld Pointer to the old WANMGR_IPV6_DATA structure. + * @param[in] pNew Pointer to the new WANMGR_IPV6_DATA structure. + * @return int Status code indicating success or failure. + */ +static int WanMgr_CopyPreviousPrefix(WANMGR_IPV6_DATA* pOld, WANMGR_IPV6_DATA* pNew) +{ + if((pOld == NULL) || (pNew == NULL)) + { + return -1; + } + strncpy(pNew->sitePrefix, pOld->sitePrefix, sizeof(pNew->sitePrefix)); + strncpy(pNew->pdIfAddress, pOld->pdIfAddress, sizeof(pNew->pdIfAddress)); + memcpy(pNew->sitePrefixOld, pOld->sitePrefixOld, BUFLEN_48); + pNew->prefixAssigned = true; + pNew->prefixCmd = pOld->prefixCmd; + pNew->prefixPltime = pOld->prefixPltime; + pNew->prefixVltime = pOld->prefixVltime; + return 0; +} +#endif + ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) { if(NULL == pVirtIf) @@ -1605,7 +1634,7 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) memset(set_value, 0, sizeof(set_value)); - CcspTraceInfo(("prefixAssigned=%d prefixCmd=%d sitePrefix=%s pdIfAddress=%s \n" + CcspTraceInfo(("IPv6 new Lease info: \nprefixAssigned=%d prefixCmd=%d sitePrefix=%s pdIfAddress=%s \n" "prefixPltime=%d prefixVltime=%d\n" "addrAssigned=%d addrCmd=%d address=%s ifname=%s\n" "maptAssigned=%d mapeAssigned=%d\n" @@ -1616,12 +1645,14 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) pNewIpcMsg->maptAssigned, pNewIpcMsg->mapeAssigned, pNewIpcMsg->dnsAssigned, pNewIpcMsg->nameserver, pNewIpcMsg->nameserver1, pNewIpcMsg->aftrAssigned, pNewIpcMsg->aftr, pNewIpcMsg->isExpired)); + WANMGR_IPV6_DATA Ipv6DataNew; // Holds the new lease from the IPC message + wanmgr_dchpv6_get_ipc_msg_info(&(Ipv6DataNew), pNewIpcMsg); + /*Check lease expiry*/ if (pNewIpcMsg->isExpired) { CcspTraceInfo(("DHCP6LeaseExpired\n")); // update current IPv6 data - wanmgr_dchpv6_get_ipc_msg_info(&(pVirtIf->IP.Ipv6Data), pNewIpcMsg); WanManager_UpdateInterfaceStatus(pVirtIf, WANMGR_IFACE_CONNECTION_IPV6_DOWN); //Free buffer @@ -1634,6 +1665,7 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) return ANSC_STATUS_SUCCESS; } +#if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) /* dhcp6c receives an IPv6 address for WAN interface */ if (pNewIpcMsg->addrAssigned) @@ -1642,13 +1674,64 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) { CcspTraceInfo(("assigned IPv6 address \n")); connected = TRUE; -#if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) || (defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //TODO: V6 handled in PAM - /* TODO: Assign IPv6 address on Wan Interface when received, if dhcpv6 client didn't assign on the ineterface. - * Currently dibbler client will assign IA_NA to the interface. - * VISM will assign the prefix on LAN interface. + + /* TODO: Assign IPv6 address on Wan Interface when received, if dhcpv6 client didn't assign on the ineterface. + * Currently dibbler client will assign IA_NA to the interface. + * VISM will assign the prefix on LAN interface. */ } + } + else if(pDhcp6cInfoCur->addrAssigned && Ipv6DataNew.prefixAssigned) + { + /* In an IPv6 lease, both IANA and IAPD details are sent together in a struct. + * If only one of them is renewed, the other field will be set to its default value. + * In this scenario, we should not consider IANA or IAPD as deleted. + * If we reach this point, only IAPD has been renewed. Use the previous IANA details. */ + + CcspTraceWarning(("%s %d IANA is not assigned in this IPC msg, but we have IANA configured from previous lease. Assuming only IAPD renewed. \n", __FUNCTION__, __LINE__)); + strncpy(Ipv6DataNew.address, pDhcp6cInfoCur->address, sizeof(Ipv6DataNew.address)); + Ipv6DataNew.addrAssigned = true; + pNewIpcMsg->addrAssigned = true; + Ipv6DataNew.addrCmd = pDhcp6cInfoCur->addrCmd; + } + + /* dhcp6c receives prefix delegation for LAN */ + if (pNewIpcMsg->prefixAssigned && !IS_EMPTY_STRING(pNewIpcMsg->sitePrefix)) + { + if (pNewIpcMsg->prefixCmd == IFADDRCONF_ADD && + pNewIpcMsg->prefixPltime != 0 && pNewIpcMsg->prefixVltime != 0) + { + CcspTraceInfo(("assigned prefix=%s \n", pNewIpcMsg->sitePrefix)); + connected = TRUE; + } + else /* IFADDRCONF_REMOVE: prefix remove */ + { + /* Validate if the prefix to be removed is the same as the stored prefix */ + if (strcmp(pDhcp6cInfoCur->sitePrefix, pNewIpcMsg->sitePrefix) == 0) + { + CcspTraceInfo(("remove prefix \n")); + WanManager_UpdateInterfaceStatus(pVirtIf, WANMGR_IFACE_CONNECTION_IPV6_DOWN); + } + } + } + else if(pDhcp6cInfoCur->prefixAssigned && Ipv6DataNew.addrAssigned) + { + /* In an IPv6 lease, both IANA and IAPD details are sent together in a struct. + * If only one of them is renewed, the other field will be set to its default value. + * In this scenario, we should not consider IANA or IAPD as deleted. + * If we reach this point, only IAPD has been renewed. Use the previous IAPD details. */ + CcspTraceWarning(("%s %d IAPD is not assigned in this IPC msg, but we have IAPD configured from previous lease. Assuming only IANA renewed. \n", __FUNCTION__, __LINE__)); + WanMgr_CopyPreviousPrefix(pDhcp6cInfoCur, &Ipv6DataNew); + } + #else + /* dhcp6c receives an IPv6 address for WAN interface */ + if (pNewIpcMsg->addrAssigned) + { + if (pNewIpcMsg->addrCmd == IFADDRCONF_ADD) + { + CcspTraceInfo(("assigned IPv6 address \n")); + connected = TRUE; if (strcmp(pDhcp6cInfoCur->address, pNewIpcMsg->address)) { syscfg_set_string(SYSCFG_FIELD_IPV6_ADDRESS, pNewIpcMsg->address); @@ -1659,7 +1742,6 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) CcspTraceInfo(("remove IPv6 address \n")); syscfg_set_string(SYSCFG_FIELD_IPV6_ADDRESS, ""); } -#endif } /* dhcp6c receives prefix delegation for LAN */ @@ -1672,7 +1754,6 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) connected = TRUE; /* Update the WAN prefix validity time in the persistent storage */ -#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) && !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //TODO: V6 handled in PAM if (pDhcp6cInfoCur->prefixVltime != pNewIpcMsg->prefixVltime) { snprintf(set_value, sizeof(set_value), "%d", pNewIpcMsg->prefixVltime); @@ -1719,7 +1800,6 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_FIELD_IPV6_PREFIX, prefix, 0); } } -#endif } else /* IFADDRCONF_REMOVE: prefix remove */ { @@ -1727,17 +1807,14 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) if (strcmp(pDhcp6cInfoCur->sitePrefix, pNewIpcMsg->sitePrefix) == 0) { CcspTraceInfo(("remove prefix \n")); -#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) && !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //TODO: V6 handled in PAM syscfg_set(NULL, SYSCFG_FIELD_IPV6_PREFIX, ""); syscfg_set(NULL, SYSCFG_FIELD_PREVIOUS_IPV6_PREFIX, ""); syscfg_set_commit(NULL, SYSCFG_FIELD_IPV6_PREFIX_ADDRESS, ""); -#endif WanManager_UpdateInterfaceStatus(pVirtIf, WANMGR_IFACE_CONNECTION_IPV6_DOWN); } } } -#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE)&& !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //TODO: V6 handled in PAM /* dhcp6c receives domain name information */ if (pNewIpcMsg->domainNameAssigned && !IS_EMPTY_STRING(pNewIpcMsg->domainName)) { @@ -1753,11 +1830,11 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) /* Even when dhcp6c is not used to get the WAN interface IP address, * * use this message as a trigger to check the WAN interface IP. * * Maybe we've been assigned an address by SLAAC.*/ - char guAddr[IP_ADDR_LENGTH] = {0}; if (!pNewIpcMsg->addrAssigned) { char guAddrPrefix[IP_ADDR_LENGTH] = {0}; + char guAddr[IP_ADDR_LENGTH] = {0}; uint32_t prefixLen = 0; ANSC_STATUS r2; @@ -1771,10 +1848,9 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) if (strcmp(pDhcp6cInfoCur->address, guAddrPrefix)) { -#if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) || (defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //TODO: V6 handled in PAM - strncpy(pVirtIf->IP.Ipv6Data.address,guAddrPrefix, sizeof(pVirtIf->IP.Ipv6Data.address)); + strncpy(Ipv6DataNew.address, guAddr, sizeof(Ipv6DataNew.address)-1); pNewIpcMsg->addrAssigned = true; -#else +#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) syscfg_set_string(SYSCFG_FIELD_IPV6_ADDRESS, guAddrPrefix); #endif } @@ -1792,59 +1868,42 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) if (connected) { - WANMGR_IPV6_DATA Ipv6DataTemp; - wanmgr_dchpv6_get_ipc_msg_info(&(Ipv6DataTemp), pNewIpcMsg); - -#if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) || (defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_))//Do not compare if pdIfAddress and sitePrefix is empty. pdIfAddress Will be calculated while configuring LAN prefix. //TODO: V6 handled in PAM - if ((strlen(Ipv6DataTemp.address) > 0 && strcmp(Ipv6DataTemp.address, pDhcp6cInfoCur->address)) || - ((Ipv6DataTemp.pdIfAddress) && (strlen(Ipv6DataTemp.pdIfAddress) > 0)&& - (strcmp(Ipv6DataTemp.pdIfAddress, pDhcp6cInfoCur->pdIfAddress))) || - ((Ipv6DataTemp.sitePrefix) && (strlen(Ipv6DataTemp.sitePrefix) > 0)&& - (strcmp(Ipv6DataTemp.sitePrefix, pDhcp6cInfoCur->sitePrefix)))|| -#else - if (strcmp(Ipv6DataTemp.address, pDhcp6cInfoCur->address) || - strcmp(Ipv6DataTemp.pdIfAddress, pDhcp6cInfoCur->pdIfAddress) || - strcmp(Ipv6DataTemp.sitePrefix, pDhcp6cInfoCur->sitePrefix) || -#endif - strcmp(Ipv6DataTemp.nameserver, pDhcp6cInfoCur->nameserver) || - strcmp(Ipv6DataTemp.nameserver1, pDhcp6cInfoCur->nameserver1)) + if ((strlen(Ipv6DataNew.address) > 0 && strcmp(Ipv6DataNew.address, pDhcp6cInfoCur->address)) || + ((strlen(Ipv6DataNew.pdIfAddress) > 0) && (strcmp(Ipv6DataNew.pdIfAddress, pDhcp6cInfoCur->pdIfAddress))) || + ((strlen(Ipv6DataNew.sitePrefix) > 0) && (strcmp(Ipv6DataNew.sitePrefix, pDhcp6cInfoCur->sitePrefix)))|| + strcmp(Ipv6DataNew.nameserver, pDhcp6cInfoCur->nameserver) || + strcmp(Ipv6DataNew.nameserver1, pDhcp6cInfoCur->nameserver1)) { CcspTraceInfo(("IPv6 configuration has been changed \n")); pVirtIf->IP.Ipv6Changed = TRUE; - CcspTraceInfo(("%s %d - RestartConnectivityCheck triggered. \n", __FUNCTION__, __LINE__)); char param_name[256] = {0}; snprintf(param_name, sizeof(param_name), "Device.X_RDK_WanManager.Interface.%d.VirtualInterface.%d.IP.IPv6Address", pVirtIf->baseIfIdx+1, pVirtIf->VirIfIdx+1); - WanMgr_Rbus_EventPublishHandler(param_name, Ipv6DataTemp.address,RBUS_STRING); + WanMgr_Rbus_EventPublishHandler(param_name, Ipv6DataNew.address,RBUS_STRING); snprintf(param_name, sizeof(param_name), "Device.X_RDK_WanManager.Interface.%d.VirtualInterface.%d.IP.IPv6Prefix", pVirtIf->baseIfIdx+1, pVirtIf->VirIfIdx+1); - WanMgr_Rbus_EventPublishHandler(param_name, Ipv6DataTemp.sitePrefix,RBUS_STRING); + WanMgr_Rbus_EventPublishHandler(param_name, Ipv6DataNew.sitePrefix,RBUS_STRING); pVirtIf->IP.RestartConnectivityCheck = TRUE; + CcspTraceInfo(("%s %d - RestartConnectivityCheck triggered. \n", __FUNCTION__, __LINE__)); } else { - /*TODO: Revisit this*/ - //call function for changing the prlft and vallft - // FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE : Handle Ip renew in handler thread. -#if !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //TODO: V6 handled in PAM - if ((WanManager_Ipv6AddrUtil(pVirtIf->Name, SET_LFT, pNewIpcMsg->prefixPltime, pNewIpcMsg->prefixVltime) < 0)) + if(pVirtIf->Status == WAN_IFACE_STATUS_UP && pNewIpcMsg->prefixPltime > 0 && pNewIpcMsg->prefixVltime > 0 ) //Update life time only if the interface is active. { - CcspTraceError(("Life Time Setting Failed")); - } - sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_RADVD_RESTART, NULL, 0); +#if !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //Do not add prefix on LAN bridge for the Comcast platforms. + //call function for changing the prlft and vallft + if ((WanManager_Ipv6AddrUtil(pVirtIf->Name, SET_LFT, pNewIpcMsg->prefixPltime, pNewIpcMsg->prefixVltime) < 0)) + { + CcspTraceError(("Life Time Setting Failed")); + } + sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_RADVD_RESTART, NULL, 0); #endif + } pVirtIf->IP.Ipv6Renewed = TRUE; } // update current IPv6 Data - memcpy(&(pVirtIf->IP.Ipv6Data), &(Ipv6DataTemp), sizeof(WANMGR_IPV6_DATA)); + memcpy(&(pVirtIf->IP.Ipv6Data), &(Ipv6DataNew), sizeof(WANMGR_IPV6_DATA)); pVirtIf->IP.Ipv6Status = WAN_IFACE_IPV6_STATE_UP; -#if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) || (defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_)) //TODO: V6 handled in PAM - //If only Ipv6 prefix is renewed, IPv6 address is not shared in the lease details. Use the detected Ipv6 address. - if(strlen(guAddr) > 0 && strlen(pVirtIf->IP.Ipv6Data.address) <= 0) - { - strncpy(pVirtIf->IP.Ipv6Data.address, guAddr, sizeof(pVirtIf->IP.Ipv6Data.address)); - } -#endif } #ifdef FEATURE_MAPT @@ -1855,6 +1914,7 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) #ifdef FEATURE_MAPT_DEBUG MaptInfo("--------- Got a new event in Wanmanager for MAPT_CONFIG ---------"); #endif + //get MAP-T previous data memcpy(&dhcp6cMAPTMsgBodyPrvs, &(pVirtIf->MAP.dhcp6cMAPTparameters), sizeof(ipc_mapt_data_t)); @@ -1872,7 +1932,7 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) } else { - if(pNewIpcMsg->prefixPltime != 0 && pNewIpcMsg->prefixVltime != 0) + if (pNewIpcMsg->prefixAssigned && !IS_EMPTY_STRING(pNewIpcMsg->sitePrefix) && pNewIpcMsg->prefixPltime != 0 && pNewIpcMsg->prefixVltime != 0) { #ifdef FEATURE_MAPT_DEBUG MaptInfo("--------- Got an event in Wanmanager for MAPT_STOP ---------"); @@ -1906,7 +1966,6 @@ int setUpLanPrefixIPv6(DML_VIRTUAL_IFACE* pVirtIf) CcspTraceInfo(("%s %d Updating SYSEVENT_CURRENT_WAN_IFNAME %s\n", __FUNCTION__, __LINE__,pVirtIf->IP.Ipv6Data.ifname)); sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_CURRENT_WAN_IFNAME, pVirtIf->IP.Ipv6Data.ifname, 0); -#if !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //TODO: V6 handled in PAM /* Enable accept ra */ WanMgr_Configure_accept_ra(pVirtIf, TRUE); @@ -1940,7 +1999,6 @@ int setUpLanPrefixIPv6(DML_VIRTUAL_IFACE* pVirtIf) sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_FIELD_TR_EROUTER_DHCPV6_CLIENT_PREFIX, pVirtIf->IP.Ipv6Data.sitePrefix, 0); } } -#endif #if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) /* moved from PAM */ int ret = RETURN_OK; @@ -1956,110 +2014,30 @@ int setUpLanPrefixIPv6(DML_VIRTUAL_IFACE* pVirtIf) if(ret != 0) { CcspTraceInfo(("Assign global ip error \n")); } -#ifdef _HUB4_PRODUCT_REQ_ - else { + else + { +#if !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //Do not add prefix on LAN bridge for the Comcast platforms. CcspTraceInfo(("%s Going to set [%s] address on brlan0 interface \n", __FUNCTION__, globalIP)); memset(cmdLine, 0, sizeof(cmdLine)); snprintf(cmdLine, sizeof(cmdLine), "ip -6 addr add %s/64 dev %s valid_lft %d preferred_lft %d", globalIP, COSA_DML_DHCPV6_SERVER_IFNAME, pVirtIf->IP.Ipv6Data.prefixVltime, pVirtIf->IP.Ipv6Data.prefixPltime); if (WanManager_DoSystemActionWithStatus(__FUNCTION__, cmdLine) != 0) CcspTraceError(("failed to run cmd: %s", cmdLine)); - - sysevent_set(sysevent_fd, sysevent_token, "lan_ipaddr_v6", globalIP, 0); - // send an event to wanmanager that Global-prefix is set - sysevent_set(sysevent_fd, sysevent_token, "lan_prefix_set", globalIP, 0); - } -#else - else { +#endif + CcspTraceInfo(("%s lan_ipaddr_v6 set to [%s] \n", __FUNCTION__, globalIP)); + /*This is for brlan0 interface */ + char pref_len[10] ={0}; + sscanf (pVirtIf->IP.Ipv6Data.sitePrefix,"%*[^/]/%s" ,pref_len); + sysevent_set(sysevent_fd, sysevent_token, "lan_prefix_v6", pref_len, 0); sysevent_set(sysevent_fd, sysevent_token, "lan_ipaddr_v6", globalIP, 0); - + sysevent_set(sysevent_fd, sysevent_token, "lan_prefix_set", globalIP, 0); //TODO: This was a event to Wanmanager. if no other process listens to it. remove it. } - // send an event to wanmanager that Global-prefix is set - sysevent_set(sysevent_fd, sysevent_token, "lan_prefix_set", globalIP, 0); -#endif memset(cmdLine, 0, sizeof(cmdLine)); snprintf(cmdLine, sizeof(cmdLine), "ip -6 route add %s dev %s", pVirtIf->IP.Ipv6Data.sitePrefix, COSA_DML_DHCPV6_SERVER_IFNAME); if (WanManager_DoSystemActionWithStatus(__FUNCTION__, cmdLine) != 0) { CcspTraceError(("failed to run cmd: %s", cmdLine)); } -#ifdef _COSA_INTEL_XB3_ARM_ - memset(cmdLine, 0, sizeof(cmdLine)); - snprintf(cmdLine, sizeof(cmdLine), "ip -6 route add %s dev %s table erouter", pVirtIf->IP.Ipv6Data.sitePrefix, COSA_DML_DHCPV6_SERVER_IFNAME); - if (WanManager_DoSystemActionWithStatus(__FUNCTION__, cmdLine) != 0) - { - CcspTraceError(("failed to run cmd: %s", cmdLine)); - } -#endif - //Restart LAN if required. - BOOL bRestartLan = FALSE; - /* we need save this for zebra to send RA - ipv6_prefix // xx:xx::/yy - */ - memset(cmdLine, 0, sizeof(cmdLine)); -#ifndef _HUB4_PRODUCT_REQ_ - snprintf(cmdLine, sizeof(cmdLine), "sysevent set ipv6_prefix %s ",v6pref); -#else -#ifdef LAN_MGR_SUPPORT - snprintf(cmdLine, sizeof(cmdLine), "sysevent set dhcpv6_raserver-restart "); -#else - snprintf(cmdLine, sizeof(cmdLine), "sysevent set zebra-restart "); -#endif -#endif - if (WanManager_DoSystemActionWithStatus(__FUNCTION__, cmdLine) != 0) - CcspTraceError(("failed to run cmd: %s", cmdLine)); - - CcspTraceWarning(("%s: globalIP %s PreviousIPv6Address %s\n", __func__, - globalIP, PreviousIPv6Address)); - if ( _ansc_strcmp(globalIP, PreviousIPv6Address ) ){ - bRestartLan = TRUE; - - //PaM may restart. When this happen, we should not overwrite previous ipv6 - if ( PreviousIPv6Address[0] ) - sysevent_set(sysevent_fd, sysevent_token, "lan_ipaddr_v6_prev", PreviousIPv6Address, 0); - - strncpy(PreviousIPv6Address, globalIP,sizeof(PreviousIPv6Address)); - }else{ - char lanrestart[8] = {0}; - sysevent_get(sysevent_fd, sysevent_token, "lan_restarted", lanrestart, sizeof(lanrestart)); - fprintf(stderr,"lan restart staus is %s \n",lanrestart); - if (strcmp("true",lanrestart) == 0) - bRestartLan = TRUE; - else - bRestartLan = FALSE; - } - CcspTraceWarning(("%s: bRestartLan %d\n", __func__, bRestartLan)); - if ( ret != 0 ) - { - CcspTraceError(("error, assign global ip error.\n")); - }else if ( bRestartLan == FALSE ){ - CcspTraceError(("Same global IP, Need not restart.\n")); - }else{ - char pref_len[10] ={0}; - - CcspTraceWarning(("Restart lan%s:%d\n", __func__,__LINE__)); - /* This is for IP.Interface.1. use */ - sysevent_set(sysevent_fd, sysevent_token, COSA_DML_DHCPV6S_ADDR_SYSEVENT_NAME, globalIP, 0); - - /*This is for brlan0 interface */ - sysevent_set(sysevent_fd, sysevent_token, "lan_ipaddr_v6", globalIP, 0); - sscanf (pVirtIf->IP.Ipv6Data.sitePrefix,"%*[^/]/%s" ,pref_len); - sysevent_set(sysevent_fd, sysevent_token, "lan_prefix_v6", pref_len, 0); - CcspTraceWarning(("%s: setting lan-restart\n", __FUNCTION__)); - sysevent_set(sysevent_fd, sysevent_token, "lan-restart", "1", 0); - - // Below code copied from CosaDmlDHCPv6sTriggerRestart(FALSE) PAm function. - int fd = 0; - char str[32] = "restart"; - fd= open(DHCPS6V_SERVER_RESTART_FIFO, O_RDWR); - if (fd < 0) - { - fprintf(stderr, "open dhcpv6 server restart fifo when writing.\n"); - return 1; - } - write( fd, str, sizeof(str) ); - close(fd); - } } /* Sysevent set moved from wanmgr_handle_dhcpv6_event_data */ @@ -2069,6 +2047,9 @@ int setUpLanPrefixIPv6(DML_VIRTUAL_IFACE* pVirtIf) { CcspTraceInfo(("assigned IPv6 address \n")); syscfg_set_string(SYSCFG_FIELD_IPV6_ADDRESS, pVirtIf->IP.Ipv6Data.address); + memset(cmdLine, 0, sizeof(cmdLine)); + snprintf(cmdLine, sizeof(cmdLine), COSA_DML_WANIface_ADDR_SYSEVENT_NAME ,pVirtIf->Name); + sysevent_set(sysevent_fd, sysevent_token, cmdLine, pVirtIf->IP.Ipv6Data.address, 0); } else /* IFADDRCONF_REMOVE */ { @@ -2076,6 +2057,7 @@ int setUpLanPrefixIPv6(DML_VIRTUAL_IFACE* pVirtIf) syscfg_set_string(SYSCFG_FIELD_IPV6_ADDRESS, ""); } } + if (pVirtIf->IP.Ipv6Data.prefixAssigned && !IS_EMPTY_STRING(pVirtIf->IP.Ipv6Data.sitePrefix)) { if (pVirtIf->IP.Ipv6Data.prefixCmd == IFADDRCONF_ADD && @@ -2103,6 +2085,7 @@ int setUpLanPrefixIPv6(DML_VIRTUAL_IFACE* pVirtIf) CcspTraceInfo(("%s %d new prefix = %s\n", __FUNCTION__, __LINE__, pVirtIf->IP.Ipv6Data.sitePrefix)); strncat(prefix, "/64",sizeof(prefix)-1); sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_FIELD_IPV6_PREFIX, prefix, 0); + sysevent_set(sysevent_fd, sysevent_token, "lan_prefix", prefix, 0); } }else /* IFADDRCONF_REMOVE: prefix remove */ { @@ -2122,6 +2105,35 @@ int setUpLanPrefixIPv6(DML_VIRTUAL_IFACE* pVirtIf) } /* Sysevent set moved from wanmgr_handle_dhcpv6_event_data end */ +#ifdef LAN_MGR_SUPPORT + //Restart RA(stateless) server + sysevent_set(sysevent_fd, sysevent_token, "dhcpv6_raserver-restart", NULL, 0); + //recreate Stateful v6 conf + sysevent_set(sysevent_fd, sysevent_token, "redirect_URL", NULL, 0); + //Restart Stateful V6 server + sysevent_set(sysevent_fd, sysevent_token, "dhcpv6-restart", NULL, 0); + +#else + sysevent_set(sysevent_fd, sysevent_token, "zebra-restart", NULL, 0); + CcspTraceWarning(("Restart lan%s:%d\n", __func__,__LINE__)); + /* This is for IP.Interface.1. use */ + sysevent_set(sysevent_fd, sysevent_token, COSA_DML_DHCPV6S_ADDR_SYSEVENT_NAME, globalIP, 0); + + CcspTraceWarning(("%s: setting lan-restart\n", __FUNCTION__)); + sysevent_set(sysevent_fd, sysevent_token, "lan-restart", "1", 0); + + // Below code copied from CosaDmlDHCPv6sTriggerRestart(FALSE) PAm function. + int fd = 0; + char str[32] = "restart"; + fd= open(DHCPS6V_SERVER_RESTART_FIFO, O_RDWR); + if (fd < 0) + { + fprintf(stderr, "open dhcpv6 server restart fifo when writing.\n"); + return 1; + } + write( fd, str, sizeof(str) ); + close(fd); +#endif #endif return RETURN_OK; } diff --git a/source/WanManager/wanmgr_interface_sm.c b/source/WanManager/wanmgr_interface_sm.c index c1d8c36..965cf31 100644 --- a/source/WanManager/wanmgr_interface_sm.c +++ b/source/WanManager/wanmgr_interface_sm.c @@ -185,13 +185,7 @@ static ANSC_STATUS WanManager_ClearDHCPData(DML_VIRTUAL_IFACE * pVirtIf); * lan ipv6 address ready to use. * @return RETURN_OK on success else RETURN_ERR *************************************************************************************/ -static int checkIpv6AddressAssignedToBridge(char *IfaceName); - -/************************************************************************************* - * @brief Check IPv6 address is ready to use or not - * @return RETURN_OK on success else RETURN_ERR - *************************************************************************************/ -static int checkIpv6LanAddressIsReadyToUse(char *IfaceName); +static int checkIpv6LanAddressIsReadyToUse(DML_VIRTUAL_IFACE* p_VirtIf); #ifdef FEATURE_MAPT @@ -224,6 +218,19 @@ static int wan_setUpMapt() { int ret = RETURN_OK; + //Configure mapt packet acceleration for supported platforms + if ( !access("/proc/sys/net/flowmgr/disable_mapt_accel", F_OK) ) + { + if (sysctl_iface_set("/proc/sys/net/flowmgr/disable_mapt_accel", NULL, "0") != 0) + { + CcspTraceError(("Failed to enable mapt packet acceleration!\n")); + } + } + else + { + CcspTraceWarning(("Mapt packet acceleration is not supported!\n")); + } + #if defined(IVI_KERNEL_SUPPORT) if (WanManager_DoSystemActionWithStatus("wanmanager", "insmod /lib/modules/`uname -r`/extra/ivi.ko") != RETURN_OK) { @@ -293,6 +300,19 @@ static int wan_tearDownMapt() } #endif //IVI_KERNEL_SUPPORT + //Configure mapt packet acceleration for supported platforms + if ( !access("/proc/sys/net/flowmgr/disable_mapt_accel", F_OK) ) + { + if (sysctl_iface_set("/proc/sys/net/flowmgr/disable_mapt_accel", NULL, "3") != 0) + { + CcspTraceError(("Failed to disable mapt packet acceleration!\n")); + } + } + else + { + CcspTraceWarning(("Mapt packet acceleration is not supported!\n")); + } + return ret; } #endif @@ -920,7 +940,14 @@ int wan_updateDNS(WanMgr_IfaceSM_Controller_t* pWanIfaceCtrl, BOOL addIPv4, BOOL return ret; } -static int checkIpv6LanAddressIsReadyToUse(char *ifname) +/* Check Duplicate Address Detection (DAD) status. The way it works is that + after an address is added to an interface, the operating system uses the + Neighbor Discovery Protocol to check if any other host on the network + has the same address. The whole process will take around 3 to 4 seconds + to complete. Also we need to check and ensure that the gateway has + a valid default route entry. + */ +static int checkIpv6LanAddressIsReadyToUse(DML_VIRTUAL_IFACE* p_VirtIf) { char buffer[BUFLEN_256] = {0}; FILE *fp_dad = NULL; @@ -932,45 +959,6 @@ static int checkIpv6LanAddressIsReadyToUse(char *ifname) char IfaceName[BUFLEN_16] = {0}; int BridgeMode = 0; -#if defined (_HUB4_PRODUCT_REQ_) //TODO: Need a generic way to check ipv6 prefix and Address. - int address_flag = 0; - struct ifaddrs *ifap = NULL; - struct ifaddrs *ifa = NULL; - char addr[INET6_ADDRSTRLEN] = {0}; - - /* We need to check the interface has got an IPV6-prefix , beacuse P-and-M can send - the same event when interface is down, so we ensure send the UP event only - when interface has an IPV6-prefix. - */ - if (!getifaddrs(&ifap)) { - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - if(strncmp(ifa->ifa_name,ETH_BRIDGE_NAME, strlen(ETH_BRIDGE_NAME))) - continue; - if (ifa->ifa_addr->sa_family != AF_INET6) - continue; - getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), addr, - sizeof(addr), NULL, 0, NI_NUMERICHOST); - if((strncmp(addr + (strlen(addr) - 3), "::1", 3) == 0)){ - address_flag = 1; - break; - } - }//for loop - freeifaddrs(ifap); - }//getifaddr close - - if(address_flag == 0) { - CcspTraceError(("%s %d address_flag Failed\n", __FUNCTION__, __LINE__)); - return -1; - } -#endif - - /* Check Duplicate Address Detection (DAD) status. The way it works is that - after an address is added to an interface, the operating system uses the - Neighbor Discovery Protocol to check if any other host on the network - has the same address. The whole process will take around 3 to 4 seconds - to complete. Also we need to check and ensure that the gateway has - a valid default route entry. - */ /*TODO: *Below Code should be removed once V6 Prefix/IP is assigned on erouter0 Instead of brlan0 for sky Devices. @@ -981,17 +969,28 @@ static int checkIpv6LanAddressIsReadyToUse(char *ifname) if (BridgeMode != 0) { memset(IfaceName, 0, sizeof(IfaceName)); - strncpy(IfaceName, ifname, sizeof(IfaceName)-1); + strncpy(IfaceName, p_VirtIf->Name, sizeof(IfaceName)-1); } CcspTraceInfo(("%s-%d: IfaceName=%s, BridgeMode=%d \n", __FUNCTION__, __LINE__, IfaceName, BridgeMode)); - for(i=0; i<15; i++) { + /* TODO: the below code assumes if the LAN ipv6 address is tentaive for 15 seconds DAD has failed. Do we need additional check? + * IANA dad is handled in the DHCPv6 client for the Wan Interface. + * Should we remove the IP from LAN bridge and request a different Delegated prefix? + * Should we use EUI-64 based Interface identifiers for all platforms? + */ + + for(i=0; i<15; i++) + { buffer[0] = '\0'; - if(dad_flag == 0) { - if ((fp_dad = v_secure_popen("r","ip address show dev %s tentative", IfaceName))) { - if(fp_dad != NULL) { + if(dad_flag == 0) + { + if ((fp_dad = v_secure_popen("r","ip address show dev %s tentative", IfaceName))) + { + if(fp_dad != NULL) + { fgets(buffer, BUFLEN_256, fp_dad); - if(strlen(buffer) == 0 ) { + if(strlen(buffer) == 0 ) + { dad_flag = 1; } v_secure_pclose(fp_dad); @@ -999,59 +998,42 @@ static int checkIpv6LanAddressIsReadyToUse(char *ifname) } } - if(route_flag == 0) { - buffer[0] = '\0'; - if ((fp_route = popen("ip -6 ro | grep default", "r"))) { - if(fp_route != NULL) { - fgets(buffer, BUFLEN_256, fp_route); - if(strlen(buffer) > 0 ) { - route_flag = 1; - } - pclose(fp_route); - } - } - } - - if(dad_flag == 0 || route_flag == 0) { + if(dad_flag == 0) + { sleep(1); } - else { + else + { break; - } + } } - if(dad_flag == 0 || route_flag == 0) { - CcspTraceError(("%s %d dad_flag[%d] route_flag[%d] Failed \n", __FUNCTION__, __LINE__,dad_flag,route_flag)); - return -1; + buffer[0] = '\0'; + if ((fp_route = popen("ip -6 ro | grep default", "r"))) { + if(fp_route != NULL) { + fgets(buffer, BUFLEN_256, fp_route); + if(strlen(buffer) > 0 ) { + route_flag = 1; + } + pclose(fp_route); + } } - return 0; -} - -static int checkIpv6AddressAssignedToBridge(char *IfaceName) -{ - char lanPrefix[BUFLEN_128] = {0}; - int ret = RETURN_ERR; - -#if (defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) && !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE)//TODO: V6 handled in PAM - CcspTraceWarning(("%s %d Ipv6 handled in PAM. No need to check here. \n",__FUNCTION__, __LINE__)); - return RETURN_OK; -#endif - sysevent_get(sysevent_fd, sysevent_token, SYSEVENT_GLOBAL_IPV6_PREFIX_SET, lanPrefix, sizeof(lanPrefix)); + if(route_flag == 0) + { + //If the default route is not present, Send a router solicit. + WanManager_send_and_receive_rs(p_VirtIf); + } - if(strlen(lanPrefix) > 0) + if(dad_flag == 0 || route_flag == 0) { - CcspTraceInfo(("%s %d lanPrefix[%s] \n", __FUNCTION__, __LINE__,lanPrefix)); - if (checkIpv6LanAddressIsReadyToUse(IfaceName) == 0) - { - ret = RETURN_OK; - } + CcspTraceError(("%s %d dad_flag[%d] route_flag[%d] Failed \n", __FUNCTION__, __LINE__,dad_flag,route_flag)); + return -1; } - return ret; + return 0; } - static void updateInterfaceToVoiceManager(WanMgr_IfaceSM_Controller_t* pWanIfaceCtrl, bool voip_started) { ANSC_STATUS retStatus = ANSC_STATUS_FAILURE; @@ -1272,8 +1254,12 @@ static int wan_tearDownIPv4(WanMgr_IfaceSM_Controller_t * pWanIfaceCtrl) DML_WAN_IFACE * pInterface = pWanIfaceCtrl->pIfaceData; DML_VIRTUAL_IFACE* p_VirtIf = WanMgr_getVirtualIfaceById(pInterface->VirtIfList, pWanIfaceCtrl->VirIfIdx); -#if !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //TODO: XB devices use the DNS of primary for backup. - /** Reset IPv4 DNS configuration. */ + /** Reset IPv4 DNS configuration. */ +#if (defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) + //TODO: XB devices use the DNS of primary for backup interfaces. Clear V4 DNS only if MAPT is up + /* FIXME: Issue in DNS ipv6 resolution when ethwan enabled *//* Workaround: We keep the ipv4 entries for name resolution */ + if(p_VirtIf->MAP.MaptStatus == WAN_IFACE_MAPT_STATE_UP && strstr(pInterface->BaseInterface, "Ethernet") == NULL) +#endif if (RETURN_OK != wan_updateDNS(pWanIfaceCtrl, FALSE, (p_VirtIf->IP.Ipv6Status == WAN_IFACE_IPV6_STATE_UP))) { CcspTraceError(("%s %d - Failed to unconfig IPv4 DNS servers \n", __FUNCTION__, __LINE__)); @@ -1283,23 +1269,13 @@ static int wan_tearDownIPv4(WanMgr_IfaceSM_Controller_t * pWanIfaceCtrl) { CcspTraceInfo(("%s %d - IPv4 DNS servers unconfig successfully \n", __FUNCTION__, __LINE__)); } -#endif - /*TODO: - *Should be removed once MAPT Unified. After PandM Added V4 default route, it got deleted here. - */ -#if defined(FEATURE_SUPPORT_MAPT_NAT46) - if (p_VirtIf->EnableMAPT == FALSE) - { -#endif if (WanManager_DelDefaultGatewayRoute(DeviceNwMode, pWanIfaceCtrl->DeviceNwModeChanged, &p_VirtIf->IP.Ipv4Data) != RETURN_OK) { CcspTraceError(("%s %d - Failed to Del default system gateway", __FUNCTION__, __LINE__)); ret = RETURN_ERR; } -#if defined(FEATURE_SUPPORT_MAPT_NAT46) - } -#endif + /* ReSet the required sysevents. */ sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_IPV4_CONNECTION_STATE, WAN_STATUS_DOWN, 0); sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_CURRENT_IPV4_LINK_STATE, WAN_STATUS_DOWN, 0); @@ -1425,7 +1401,8 @@ static int wan_tearDownIPv6(WanMgr_IfaceSM_Controller_t * pWanIfaceCtrl) DML_WAN_IFACE * pInterface = pWanIfaceCtrl->pIfaceData; DML_VIRTUAL_IFACE* p_VirtIf = WanMgr_getVirtualIfaceById(pInterface->VirtIfList, pWanIfaceCtrl->VirIfIdx); -#if !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //TODO: XB devices use the DNS of primary for backup. + //TODO: FIXME: XB devices use the DNS of primary for backup and doesn't deconfigure the primary ipv6 prefix from the LAN interface. +#if !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) /** Reset IPv6 DNS configuration. */ if (RETURN_OK == wan_updateDNS(pWanIfaceCtrl, (p_VirtIf->IP.Ipv4Status == WAN_IFACE_IPV4_STATE_UP), FALSE)) { @@ -1437,6 +1414,7 @@ static int wan_tearDownIPv6(WanMgr_IfaceSM_Controller_t * pWanIfaceCtrl) ret = RETURN_ERR; } +#endif /** Unconfig IPv6. */ if ( WanManager_Ipv6AddrUtil(p_VirtIf->Name, DEL_ADDR,0,0) < 0) { @@ -1462,7 +1440,6 @@ static int wan_tearDownIPv6(WanMgr_IfaceSM_Controller_t * pWanIfaceCtrl) sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_IPV6_CONNECTION_STATE, WAN_STATUS_DOWN, 0); sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_GLOBAL_IPV6_PREFIX_SET, "", 0); sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_FIREWALL_RESTART, NULL, 0); -#endif //RBUS_WAN_IP #if defined (RBUS_WAN_IP) @@ -1722,6 +1699,7 @@ static ANSC_STATUS WanManager_ClearDHCPData(DML_VIRTUAL_IFACE * pVirtIf) pVirtIf->IP.Ipv6Changed = FALSE; pVirtIf->IP.Ipv6Renewed = FALSE; memset(&(pVirtIf->IP.Ipv6Data), 0, sizeof(WANMGR_IPV6_DATA)); + memset(&(pVirtIf->IP.Ipv6Route), 0, sizeof(WANMGR_IPV6_RA_DATA)); pVirtIf->IP.Dhcp6cPid = 0; if(pVirtIf->IP.pIpcIpv6Data != NULL) { @@ -1767,19 +1745,6 @@ static eWanState_t wan_transition_start(WanMgr_IfaceSM_Controller_t* pWanIfaceCt CcspTraceInfo(("%s %d - Already WAN interface %s created\n", __FUNCTION__, __LINE__, p_VirtIf->Name)); } -#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) - if(pInterface->IfaceType != REMOTE_IFACE) - { - /* TODO: This is a workaround for the platforms using same Wan Name.*/ - char param_value[256] ={0}; - char param_name[512] ={0}; - int retPsmGet = CCSP_SUCCESS; - _ansc_sprintf(param_name, PSM_WANMANAGER_IF_VIRIF_NAME, (p_VirtIf->baseIfIdx + 1), (p_VirtIf->VirIfIdx + 1)); - retPsmGet = WanMgr_RdkBus_GetParamValuesFromDB(param_name,param_value,sizeof(param_value)); - AnscCopyString(p_VirtIf->Name, (retPsmGet == CCSP_SUCCESS && (strlen(param_value) > 0 )) ? param_value: "erouter0"); - CcspTraceInfo(("%s %d VIRIF_NAME is copied from PSM. %s\n", __FUNCTION__, __LINE__, p_VirtIf->Name)); - } -#endif /*TODO: VLAN should not be set for Remote Interface, for More info, refer RDKB-42676*/ if( p_VirtIf->VLAN.Enable == TRUE && p_VirtIf->VLAN.Status == WAN_IFACE_LINKSTATUS_DOWN && pInterface->IfaceType != REMOTE_IFACE) { @@ -1990,12 +1955,7 @@ static eWanState_t wan_transition_wan_validated(WanMgr_IfaceSM_Controller_t* pWa } if(p_VirtIf->IP.IPv6Source == DML_WAN_IP_SOURCE_DHCP && (p_VirtIf->IP.Dhcp6cPid == 0) && - (p_VirtIf->IP.Mode == DML_WAN_IP_MODE_DUAL_STACK || p_VirtIf->IP.Mode == DML_WAN_IP_MODE_IPV6_ONLY) -#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) - //TODO: Don't start ipv6 while validating primary for Comcast - && p_VirtIf->IP.RestartV6Client ==FALSE -#endif - ) + (p_VirtIf->IP.Mode == DML_WAN_IP_MODE_DUAL_STACK || p_VirtIf->IP.Mode == DML_WAN_IP_MODE_IPV6_ONLY)) { /* Start all interface with accept ra disbaled */ WanMgr_Configure_accept_ra(p_VirtIf, FALSE); @@ -2669,7 +2629,6 @@ static eWanState_t wan_transition_mapt_up(WanMgr_IfaceSM_Controller_t* pWanIface DML_WAN_IFACE* pInterface = pWanIfaceCtrl->pIfaceData; DML_VIRTUAL_IFACE* p_VirtIf = WanMgr_getVirtualIfaceById(pInterface->VirtIfList, pWanIfaceCtrl->VirIfIdx); -#if defined(FEATURE_MAPT) // verify mapt configuration memset(&(p_VirtIf->MAP.MaptConfig), 0, sizeof(WANMGR_MAPT_CONFIG_DATA)); if (WanManager_VerifyMAPTConfiguration(&(p_VirtIf->MAP.dhcp6cMAPTparameters), &(p_VirtIf->MAP.MaptConfig)) == ANSC_STATUS_FAILURE) @@ -2683,7 +2642,6 @@ static eWanState_t wan_transition_mapt_up(WanMgr_IfaceSM_Controller_t* pWanIface CcspTraceInfo(("%s %d - MAPT Configuration verification success \n", __FUNCTION__, __LINE__)); } -#endif p_VirtIf->MAP.MaptChanged = FALSE; @@ -2693,14 +2651,12 @@ static eWanState_t wan_transition_mapt_up(WanMgr_IfaceSM_Controller_t* pWanIface wan_transition_ipv4_up(pWanIfaceCtrl); } -#if defined(FEATURE_MAPT) // configure mapt module ret = wan_setUpMapt(); if (ret != RETURN_OK) { CcspTraceError(("%s %d - Failed to configure MAP-T \n", __FUNCTION__, __LINE__)); } -#endif if (p_VirtIf->IP.Dhcp4cPid > 0) { @@ -2715,7 +2671,6 @@ static eWanState_t wan_transition_mapt_up(WanMgr_IfaceSM_Controller_t* pWanIface { wan_transition_ipv4_down(pWanIfaceCtrl); -#if defined(FEATURE_MAPT) #if defined(IVI_KERNEL_SUPPORT) snprintf(cmdEnableIpv4Traffic,sizeof(cmdEnableIpv4Traffic),"ip ro rep default dev %s", p_VirtIf->Name); #elif defined(NAT46_KERNEL_SUPPORT) @@ -2728,7 +2683,6 @@ static eWanState_t wan_transition_mapt_up(WanMgr_IfaceSM_Controller_t* pWanIface { CcspTraceError(("%s %d - Failed to run: %s \n", __FUNCTION__, __LINE__, cmdEnableIpv4Traffic)); } -#endif } if( p_VirtIf->PPP.Enable == TRUE ) @@ -2740,7 +2694,6 @@ static eWanState_t wan_transition_mapt_up(WanMgr_IfaceSM_Controller_t* pWanIface CcspTraceInfo(("%s %d - net.ipv4.ip_forward set to 1 \n", __FUNCTION__, __LINE__)); v_secure_system("sysctl -w net.ipv4.ip_forward=1"); -#if defined(FEATURE_MAPT) /* Configure MAPT. */ if (WanManager_ProcessMAPTConfiguration(&(p_VirtIf->MAP.dhcp6cMAPTparameters), &(p_VirtIf->MAP.MaptConfig), pInterface->Name, p_VirtIf->IP.Ipv6Data.ifname) != RETURN_OK) { @@ -2748,7 +2701,6 @@ static eWanState_t wan_transition_mapt_up(WanMgr_IfaceSM_Controller_t* pWanIface CcspTraceInfo(("%s %d - Interface '%s' - TRANSITION to State=%d \n", __FUNCTION__, __LINE__, pInterface->Name, p_VirtIf->eCurrentState)); return(p_VirtIf->eCurrentState); } -#endif sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_FIREWALL_RESTART, NULL, 0); @@ -2771,18 +2723,19 @@ static eWanState_t wan_transition_mapt_down(WanMgr_IfaceSM_Controller_t* pWanIfa WanManager_UpdateInterfaceStatus (p_VirtIf, WANMGR_IFACE_MAPT_STOP); -#if defined(FEATURE_MAPT) - //TODO: check p_VirtIf->Status , WAN_IFACE_STATUS_UP before tearing down. - if (wan_tearDownMapt() != RETURN_OK) + if(p_VirtIf->Status == WAN_IFACE_STATUS_UP) { - CcspTraceError(("%s %d - Failed to tear down MAP-T for %s \n", __FUNCTION__, __LINE__, p_VirtIf->Name)); + if (wan_tearDownMapt() != RETURN_OK) + { + CcspTraceError(("%s %d - Failed to tear down MAP-T for %s \n", __FUNCTION__, __LINE__, p_VirtIf->Name)); + } } if (WanManager_ResetMAPTConfiguration(pInterface->Name, p_VirtIf->Name) != RETURN_OK) { CcspTraceError(("%s %d Error resetting MAP-T configuration", __FUNCTION__, __LINE__)); } -#endif + /* Clear DHCPv4 client */ WanManager_UpdateInterfaceStatus (p_VirtIf, WANMGR_IFACE_CONNECTION_DOWN); memset(&(p_VirtIf->IP.Ipv4Data), 0, sizeof(WANMGR_IPV4_DATA)); @@ -2843,15 +2796,6 @@ static eWanState_t wan_transition_exit(WanMgr_IfaceSM_Controller_t* pWanIfaceCtr Update_Interface_Status(); CcspTraceInfo(("%s %d - Interface '%s' - EXITING STATE MACHINE\n", __FUNCTION__, __LINE__, pInterface->Name)); -#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) - /* TODO:This is a workaround for the platforms using same Wan Name.*/ - if(pInterface->IfaceType != REMOTE_IFACE) - { - memset(p_VirtIf->Name, 0, sizeof(p_VirtIf->Name)); - CcspTraceInfo(("%s %d clear VIRIF_NAME \n", __FUNCTION__, __LINE__)); - } -#endif - p_VirtIf->Interface_SM_Running = FALSE; return WAN_STATE_EXIT; @@ -3190,12 +3134,7 @@ static eWanState_t wan_state_obtaining_ip_addresses(WanMgr_IfaceSM_Controller_t* } if(p_VirtIf->IP.IPv6Source == DML_WAN_IP_SOURCE_DHCP && - (p_VirtIf->IP.Mode == DML_WAN_IP_MODE_IPV6_ONLY || p_VirtIf->IP.Mode == DML_WAN_IP_MODE_DUAL_STACK) -#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) - //TODO: Don't start ipv6 while validating primary for Comcast - && p_VirtIf->IP.RestartV6Client ==FALSE -#endif - ) + (p_VirtIf->IP.Mode == DML_WAN_IP_MODE_IPV6_ONLY || p_VirtIf->IP.Mode == DML_WAN_IP_MODE_DUAL_STACK)) { if(p_VirtIf->IP.Dhcp6cPid <= 0) { @@ -3253,14 +3192,10 @@ static eWanState_t wan_state_obtaining_ip_addresses(WanMgr_IfaceSM_Controller_t* p_VirtIf->IP.Ipv6Changed = FALSE; return WAN_STATE_OBTAINING_IP_ADDRESSES; } - if (checkIpv6AddressAssignedToBridge(p_VirtIf->Name) == RETURN_OK) + if (checkIpv6LanAddressIsReadyToUse(p_VirtIf) == RETURN_OK) { return wan_transition_ipv6_up(pWanIfaceCtrl); } - else - { - wanmgr_Ipv6Toggle(); - } } else { @@ -3318,30 +3253,6 @@ static eWanState_t wan_state_standby(WanMgr_IfaceSM_Controller_t* pWanIfaceCtrl) } else if (pInterface->Selection.Status == WAN_IFACE_ACTIVE) { -#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) - /* This check is a workaround to reconfigure IPv6 from PAM*/ - if(p_VirtIf->IP.RestartV6Client ==TRUE) - { - CcspTraceInfo(("%s %d: Restart Ipv6 client triggered. \n", __FUNCTION__, __LINE__)); - /* Stops DHCPv6 client */ - if(p_VirtIf->IP.Dhcp6cPid > 0) - { - CcspTraceInfo(("%s %d: Stopping DHCP v6\n", __FUNCTION__, __LINE__)); - WanManager_StopDhcpv6Client(p_VirtIf->Name, STOP_DHCP_WITH_RELEASE); // release dhcp lease - p_VirtIf->IP.Dhcp6cPid = 0; - } - - if(p_VirtIf->IP.IPv6Source == DML_WAN_IP_SOURCE_DHCP && - (p_VirtIf->IP.Mode == DML_WAN_IP_MODE_DUAL_STACK || p_VirtIf->IP.Mode == DML_WAN_IP_MODE_IPV6_ONLY)) - { - /* Start DHCPv6 Client */ - p_VirtIf->IP.Dhcp6cPid = WanManager_StartDhcpv6Client(p_VirtIf, pInterface->IfaceType); - CcspTraceInfo(("%s %d - Started dhcpv6 client on interface %s, dhcpv6_pid %d \n", __FUNCTION__, __LINE__, p_VirtIf->Name, p_VirtIf->IP.Dhcp6cPid)); - } - p_VirtIf->IP.RestartV6Client = FALSE; - } - else -#endif if (p_VirtIf->IP.Ipv6Status == WAN_IFACE_IPV6_STATE_UP) { if (p_VirtIf->IP.Ipv6Changed == TRUE) @@ -3350,17 +3261,13 @@ static eWanState_t wan_state_standby(WanMgr_IfaceSM_Controller_t* pWanIfaceCtrl) { CcspTraceInfo((" %s %d - configure IPv6 prefix \n", __FUNCTION__, __LINE__)); } - p_VirtIf->IP.Ipv6Changed == FALSE; + p_VirtIf->IP.Ipv6Changed = FALSE; } - if (checkIpv6AddressAssignedToBridge(p_VirtIf->Name) == RETURN_OK) + if (checkIpv6LanAddressIsReadyToUse(p_VirtIf) == RETURN_OK) { ret = wan_transition_ipv6_up(pWanIfaceCtrl); CcspTraceInfo((" %s %d - IPv6 Address Assigned to Bridge Yet.\n", __FUNCTION__, __LINE__)); } - else - { - wanmgr_Ipv6Toggle(); - } } if (p_VirtIf->IP.Ipv4Status == WAN_IFACE_IPV4_STATE_UP) { @@ -3368,6 +3275,13 @@ static eWanState_t wan_state_standby(WanMgr_IfaceSM_Controller_t* pWanIfaceCtrl) } return ret; } + + //FIXME : IPoE health check won't work if the interface is standby + if(p_VirtIf->IP.RestartConnectivityCheck == TRUE && p_VirtIf->IP.ConnectivityCheckType == WAN_CONNECTIVITY_TYPE_TAD) + { + WanMgr_StartConnectivityCheck(pWanIfaceCtrl); + } + return WAN_STATE_STANDBY; } @@ -3391,9 +3305,6 @@ static eWanState_t wan_state_ipv4_leased(WanMgr_IfaceSM_Controller_t* pWanIfaceC p_VirtIf->IP.Dhcp6cPid = WanManager_StartDhcpv6Client(p_VirtIf, pInterface->IfaceType); CcspTraceInfo(("%s %d - Started dhcpv6 client on interface %s, dhcpv6_pid %d \n", __FUNCTION__, __LINE__, p_VirtIf->Name, p_VirtIf->IP.Dhcp6cPid)); CcspTraceInfo(("%s %d - Interface '%s' - Running in Dual Stack IP Mode\n", __FUNCTION__, __LINE__, pInterface->Name)); -#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) - p_VirtIf->IP.RestartV6Client = FALSE; -#endif } // Start DHCP apps if not started @@ -3442,29 +3353,6 @@ static eWanState_t wan_state_ipv4_leased(WanMgr_IfaceSM_Controller_t* pWanIfaceC CcspTraceError(("%s %d - Failed to tear down IPv4 for %s Interface \n", __FUNCTION__, __LINE__, p_VirtIf->Name)); } } -#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) - /* This check is a workaround to reconfigure IPv6 from PAM*/ - else if(p_VirtIf->IP.RestartV6Client ==TRUE) - { - CcspTraceInfo(("%s %d: Restart Ipv6 client triggered. \n", __FUNCTION__, __LINE__)); - /* Stops DHCPv6 client */ - if(p_VirtIf->IP.Dhcp6cPid > 0) - { - CcspTraceInfo(("%s %d: Stopping DHCP v6\n", __FUNCTION__, __LINE__)); - WanManager_StopDhcpv6Client(p_VirtIf->Name, STOP_DHCP_WITH_RELEASE); - p_VirtIf->IP.Dhcp6cPid = 0; - } - - if(p_VirtIf->IP.IPv6Source == DML_WAN_IP_SOURCE_DHCP && - (p_VirtIf->IP.Mode == DML_WAN_IP_MODE_DUAL_STACK || p_VirtIf->IP.Mode == DML_WAN_IP_MODE_IPV6_ONLY)) - { - /* Start DHCPv6 Client */ - p_VirtIf->IP.Dhcp6cPid = WanManager_StartDhcpv6Client(p_VirtIf, pInterface->IfaceType); - CcspTraceInfo(("%s %d - Started dhcpv6 client on interface %s, dhcpv6_pid %d \n", __FUNCTION__, __LINE__, p_VirtIf->Name, p_VirtIf->IP.Dhcp6cPid)); - } - p_VirtIf->IP.RestartV6Client = FALSE; - } -#endif else if (p_VirtIf->IP.Ipv6Status == WAN_IFACE_IPV6_STATE_UP) { if(p_VirtIf->IP.Ipv6Changed == TRUE) @@ -3478,14 +3366,10 @@ static eWanState_t wan_state_ipv4_leased(WanMgr_IfaceSM_Controller_t* pWanIfaceC p_VirtIf->IP.Ipv6Changed = FALSE; return WAN_STATE_IPV4_LEASED; } - if (checkIpv6AddressAssignedToBridge(p_VirtIf->Name) == RETURN_OK) + if (checkIpv6LanAddressIsReadyToUse(p_VirtIf) == RETURN_OK) { return wan_transition_ipv6_up(pWanIfaceCtrl); } - else - { - wanmgr_Ipv6Toggle(); - } } else if (p_VirtIf->IP.Ipv4Renewed == TRUE) { @@ -3593,10 +3477,10 @@ static eWanState_t wan_state_ipv6_leased(WanMgr_IfaceSM_Controller_t* pWanIfaceC pInterface->Selection.Status == WAN_IFACE_ACTIVE && p_VirtIf->MAP.MaptStatus == WAN_IFACE_MAPT_STATE_UP) { - if (checkIpv6AddressAssignedToBridge(p_VirtIf->Name) == RETURN_OK) // Wait for default gateway before MAP-T configuration + if (checkIpv6LanAddressIsReadyToUse(p_VirtIf) == RETURN_OK) // Wait for default gateway before MAP-T configuration { return wan_transition_mapt_up(pWanIfaceCtrl); - } //wanmgr_Ipv6Toggle() is called below. + } } else if (p_VirtIf->EnableMAPT == TRUE && pInterface->Selection.Status == WAN_IFACE_ACTIVE && @@ -3615,7 +3499,9 @@ static eWanState_t wan_state_ipv6_leased(WanMgr_IfaceSM_Controller_t* pWanIfaceC WanMgr_SendMsgTo_ConnectivityCheck(pWanIfaceCtrl, CONNECTION_MSG_IPV6 , TRUE); p_VirtIf->IP.Ipv6Renewed = FALSE; } - wanmgr_Ipv6Toggle(); + + WanMgr_CheckDefaultRA(p_VirtIf); + #if defined(FEATURE_IPOE_HEALTH_CHECK) && defined(IPOE_HEALTH_CHECK_LAN_SYNC_SUPPORT) if(lanState == LAN_STATE_STOPPED) { @@ -3729,10 +3615,10 @@ static eWanState_t wan_state_dual_stack_active(WanMgr_IfaceSM_Controller_t* pWan pInterface->Selection.Status == WAN_IFACE_ACTIVE && p_VirtIf->MAP.MaptStatus == WAN_IFACE_MAPT_STATE_UP) { - if (checkIpv6AddressAssignedToBridge(p_VirtIf->Name) == RETURN_OK) // Wait for default gateway before MAP-T configuration + if (checkIpv6LanAddressIsReadyToUse(p_VirtIf) == RETURN_OK) // Wait for default gateway before MAP-T configuration { return wan_transition_mapt_up(pWanIfaceCtrl); - }//wanmgr_Ipv6Toggle() is called below. + } } else if (p_VirtIf->EnableMAPT == TRUE && pInterface->Selection.Status == WAN_IFACE_ACTIVE && @@ -3759,8 +3645,8 @@ static eWanState_t wan_state_dual_stack_active(WanMgr_IfaceSM_Controller_t* pWan // Start DHCP apps if not started WanMgr_MonitorDhcpApps(pWanIfaceCtrl); + WanMgr_CheckDefaultRA(p_VirtIf); - wanmgr_Ipv6Toggle(); #if defined(FEATURE_IPOE_HEALTH_CHECK) && defined(IPOE_HEALTH_CHECK_LAN_SYNC_SUPPORT) if(lanState == LAN_STATE_STOPPED) { @@ -3905,7 +3791,7 @@ static eWanState_t wan_state_mapt_active(WanMgr_IfaceSM_Controller_t* pWanIfaceC // Start DHCP apps if not started WanMgr_MonitorDhcpApps(pWanIfaceCtrl); - wanmgr_Ipv6Toggle(); + WanMgr_CheckDefaultRA(p_VirtIf); #if defined(FEATURE_IPOE_HEALTH_CHECK) && defined(IPOE_HEALTH_CHECK_LAN_SYNC_SUPPORT) if(lanState == LAN_STATE_STOPPED) { diff --git a/source/WanManager/wanmgr_ipc.c b/source/WanManager/wanmgr_ipc.c index ec6023e..129961a 100644 --- a/source/WanManager/wanmgr_ipc.c +++ b/source/WanManager/wanmgr_ipc.c @@ -73,7 +73,7 @@ static ANSC_STATUS WanMgr_IpcNewIpv4Msg(ipc_dhcpv4_data_t* pNewIpv4Msg) while((retStatus != ANSC_STATUS_SUCCESS) && (try < WANMGR_MAX_IPC_PROCCESS_TRY)) { //get iface data - DML_VIRTUAL_IFACE* pVirtIf = WanMgr_GetVirtualIfaceByName_locked(pNewIpv4Msg->dhcpcInterface); + DML_VIRTUAL_IFACE* pVirtIf = WanMgr_GetVIfByName_VISM_running_locked(pNewIpv4Msg->dhcpcInterface); if(pVirtIf != NULL) { //check if previously message was already handled @@ -114,7 +114,7 @@ static ANSC_STATUS WanMgr_IpcNewIpv6Msg(ipc_dhcpv6_data_t* pNewIpv6Msg) while((retStatus != ANSC_STATUS_SUCCESS) && (try < WANMGR_MAX_IPC_PROCCESS_TRY)) { //get iface data - DML_VIRTUAL_IFACE* pVirtIf = WanMgr_GetVirtualIfaceByName_locked(pNewIpv6Msg->ifname); + DML_VIRTUAL_IFACE* pVirtIf = WanMgr_GetVIfByName_VISM_running_locked(pNewIpv6Msg->ifname); if(pVirtIf != NULL) { //check if previously message was already handled @@ -144,34 +144,6 @@ static ANSC_STATUS WanMgr_IpcNewIpv6Msg(ipc_dhcpv6_data_t* pNewIpv6Msg) return retStatus; } -/*TODO: - *the below code should be removed once Unified MAPT Implemented. - */ -static ANSC_STATUS WanMgr_MaptStatusChanged(ipc_dhcpv6_data_t* pNewMaptMsg) -{ - ANSC_STATUS retStatus = ANSC_STATUS_FAILURE; - - CcspTraceInfo(("%s %d - Received Ipc MAMPT-Msg for %s\n", __FUNCTION__, __LINE__, pNewMaptMsg->ifname)); - - DML_VIRTUAL_IFACE* pVirtIf = WanMgr_GetVirtualIfaceByName_locked(pNewMaptMsg->ifname); - if(pVirtIf != NULL) - { - if (pNewMaptMsg->maptAssigned == TRUE) - { - WanManager_UpdateInterfaceStatus(pVirtIf, WANMGR_IFACE_MAPT_START); - retStatus = ANSC_STATUS_SUCCESS; - } - else if (pNewMaptMsg->maptAssigned == FALSE) - { - WanManager_UpdateInterfaceStatus(pVirtIf, WANMGR_IFACE_MAPT_STOP); - retStatus = ANSC_STATUS_SUCCESS; - } - WanMgr_VirtualIfaceData_release(pVirtIf); - } - - return retStatus; -} - ANSC_STATUS WanMgr_SetInterfaceStatus(char *ifName, wanmgr_iface_status_t state) { DML_VIRTUAL_IFACE* pVirtIf = WanMgr_GetVirtualIfaceByName_locked(ifName); @@ -351,16 +323,6 @@ static void* IpcServerThread( void *arg ) } break; #endif - /*TODO: - *The below code should be removed once Unified MAPT Implemented. - */ - case MAPT_STATE_CHANGED: - if (WanMgr_MaptStatusChanged(&(ipc_msg.data.dhcpv6)) != ANSC_STATUS_SUCCESS) - { - CcspTraceError(("[%s-%d] Failed to proccess MAPT state change message for %s \n", __FUNCTION__, __LINE__,ipc_msg.data.dhcpv6.ifname)); - } - break; - default: CcspTraceError(("[%s-%d] Invalid Message sent to Wan Manager\n", __FUNCTION__, __LINE__)); } @@ -523,6 +485,12 @@ ANSC_STATUS WanMgr_StartIpcServer() CcspTraceInfo(("%s %d - IPC Thread Started Successfully\n", __FUNCTION__, __LINE__)); retStatus = ANSC_STATUS_SUCCESS; } + +#if defined(WAN_MANAGER_UNIFICATION_ENABLED) && !defined( RDKB_EXTENDER_ENABLED) + //TODO: XLE is still using the legacy CcspPaM dhcpv6c_dbg_thrd thread + WanMgr_DhcpV6MsgHandlerInit(); +#endif + return retStatus ; } diff --git a/source/WanManager/wanmgr_net_utils.c b/source/WanManager/wanmgr_net_utils.c index a2f8714..68f20d5 100644 --- a/source/WanManager/wanmgr_net_utils.c +++ b/source/WanManager/wanmgr_net_utils.c @@ -156,8 +156,8 @@ static ANSC_STATUS setDibblerClientEnable(BOOL * enable); ****************************************************************************/ #define SERIALIZATION_DATA "/tmp/serial.txt" static ANSC_STATUS GetAdslUsernameAndPassword(char *Username, char *Password); -static int WanManager_CalculatePsidAndV4Index(char *pdIPv6Prefix, int v6PrefixLen, int iapdPrefixLen, int v4PrefixLen, int *psidValue, int *ipv4IndexValue, int *psidLen); #endif +static int WanManager_CalculatePsidAndV4Index(char *pdIPv6Prefix, int v6PrefixLen, int iapdPrefixLen, int v4PrefixLen, int *psidValue, int *ipv4IndexValue, int *psidLen); #if defined(FEATURE_464XLAT) #define XLAT_INTERFACE "xlat" @@ -488,11 +488,12 @@ int WanManager_Ipv6AddrUtil(char *ifname, Ipv6OperType opr, int preflft, int val { if (strlen(prefix) > 0) { +#if !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //Do not delete prefix from LAn bridge for the comcast platforms. memset(cmdLine, 0, sizeof(cmdLine)); snprintf(cmdLine, sizeof(cmdLine), "ip -6 addr del %s/64 dev %s", prefixAddr, IfaceName); if (WanManager_DoSystemActionWithStatus("ip -6 addr del ADDR dev xxxx", cmdLine) != 0) CcspTraceError(("failed to run cmd: %s", cmdLine)); - +#endif memset(cmdLine, 0, sizeof(cmdLine)); #if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) snprintf(cmdLine, sizeof(cmdLine), "ip -6 route flush match %s ", prefix); @@ -557,12 +558,7 @@ uint32_t WanManager_StartDhcpv6Client(DML_VIRTUAL_IFACE* pVirtIf, IFACE_TYPE Ifa params.ifType = IfaceType; CcspTraceInfo(("Enter WanManager_StartDhcpv6Client for %s \n", pVirtIf->Name)); - -#if (defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) //TODO: ipv6 handled in PAM - //Enable accept_ra while starting dhcpv6 for comcast devices. - WanMgr_Configure_accept_ra(pVirtIf, TRUE); - usleep(500000); //sleep for 500 milli seconds -#endif + WanManager_send_and_receive_rs(pVirtIf); pid = start_dhcpv6_client(¶ms); pVirtIf->IP.Dhcp6cPid = pid; @@ -758,6 +754,40 @@ static ANSC_STATUS WanManager_GetLANIPAddress(char *ipAddress, size_t length) return ANSC_STATUS_SUCCESS; } +#define UPnPIGD_ENABLE_DML "Device.UPnP.Device.UPnPIGD" +BOOL g_UPnPIGDServiceStopped = false; +int WanMgr_RdkBus_ConfigureUPnPIGDService (BOOL configure_UPnPIGD) +{ + if( configure_UPnPIGD && g_UPnPIGDServiceStopped) + { + CcspTraceInfo(("%s %d: upnp_igd was stopped while configuring MAPT. Starting the service again\n", __FUNCTION__, __LINE__)); + if (WanMgr_RdkBus_SetParamValues( PAM_COMPONENT_NAME, PAM_DBUS_PATH, UPnPIGD_ENABLE_DML, "true", ccsp_boolean, TRUE ) == ANSC_STATUS_SUCCESS) + { + CcspTraceInfo(("%s %d: Succesfully set %s to true\n", __FUNCTION__, __LINE__, UPnPIGD_ENABLE_DML)); + } + g_UPnPIGDServiceStopped = false; + } + else if(!configure_UPnPIGD) + { + char syscfg_enabled[BUFLEN_8] = {0}; + syscfg_get(NULL, "upnp_igd_enabled", syscfg_enabled, sizeof(syscfg_enabled)); + if('1' == syscfg_enabled[0]) + { + CcspTraceInfo(("%s %d: Stopping UPnPIGD service \n", __FUNCTION__, __LINE__)); + if (WanMgr_RdkBus_SetParamValues( PAM_COMPONENT_NAME, PAM_DBUS_PATH, UPnPIGD_ENABLE_DML, "false", ccsp_boolean, TRUE ) == ANSC_STATUS_SUCCESS) + { + CcspTraceInfo(("%s %d: Succesfully set %s to false\n", __FUNCTION__, __LINE__, UPnPIGD_ENABLE_DML)); + } + g_UPnPIGDServiceStopped = true; + } + else + { + CcspTraceInfo(("%s %d: UPnPIGD is not enabled in syscfg upnp_igd_enabled\n", __FUNCTION__, __LINE__)); + } + } + return 0; +} + ANSC_STATUS WanManager_VerifyMAPTConfiguration(ipc_mapt_data_t *dhcp6cMAPTMsgBody, WANMGR_MAPT_CONFIG_DATA *MaptConfig) { int ret = RETURN_OK; @@ -884,6 +914,13 @@ int WanManager_ProcessMAPTConfiguration(ipc_mapt_data_t *dhcp6cMAPTMsgBody, WANM } MaptInfo("mapt: MTU Size = %d \n", mtu_size_mapt); + /* Stopping UPnP, if mapt ratio is not 1:1 */ + if(dhcp6cMAPTMsgBody->ratio > 1) + { + CcspTraceInfo(("%s %d: MAPT ratio is %d. Stopping UPnP IGD \n", __FUNCTION__, __LINE__, dhcp6cMAPTMsgBody->ratio)); + WanMgr_RdkBus_ConfigureUPnPIGDService(false); + } + /* RM16042: Since erouter0 is vlan interface on top of eth3 ptm, we need to first set the MTU size of eth3 to 1520 and then change MTU of erouter0. Otherwise we can't configure MTU as we are getting `Numerical result out of range` error. @@ -1197,6 +1234,26 @@ int WanManager_ProcessMAPTConfiguration(ipc_mapt_data_t *dhcp6cMAPTMsgBody, WANM } #endif // NAT46_KERNEL_SUPPORT +/* + * Any VoIP/SIP application running on the CPE itself or in the home LAN, MUST send some form of SIP keepalives (Options or Register messages), + * more frequent than the nf_conntrack_udp_timeout_stream value to allow unsolicited inbound calls to not be blocked by the firewall. + * Either increase this value above the SIP keepalive frequency, or ensure SIP applications are configured to send keepalives more frequent than Linux's default value of 120 seconds. + */ +#if defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) + // This is a configuration specific for Comcast. Sky devices has nf_conntrack_udp_timeout_stream set to 300 seconds. + CcspTraceInfo(("%s %d :Setting nf_conntrack_udp_timeout to 30 seconds for MAPT! \n", __FUNCTION__, __LINE__)); + if ( v_secure_system("sysctl -w net.netfilter.nf_conntrack_udp_timeout=30") ) + { + CcspTraceError(("%s %d : Failed to set nf_conntrack_udp_timeout! \n", __FUNCTION__, __LINE__)); + } + + CcspTraceInfo(("%s %d :Setting nf_conntrack_udp_timeout_stream to 120 seconds for MAPT! \n", __FUNCTION__, __LINE__)); + if ( v_secure_system("sysctl -w net.netfilter.nf_conntrack_udp_timeout_stream=120") ) + { + CcspTraceError(("%s %d : Failed to set nf_conntrack_udp_timeout_stream! \n", __FUNCTION__, __LINE__)); + } +#endif + #if defined(IVI_KERNEL_SUPPORT) || (NAT46_KERNEL_SUPPORT) /** * Firewall rules are changed to utopia firewall @@ -1545,6 +1602,10 @@ int WanManager_ResetMAPTConfiguration(const char *baseIf, const char *vlanIf) * `mapt_configure_flag` and restart the firewall. */ //Reset MAP sysevent parameters maptInfo_reset(); + + /* Starting UPnP, if we have stopped it while configuring MAPT */ + WanMgr_RdkBus_ConfigureUPnPIGDService(true); + sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_FIREWALL_RESTART, NULL, 0); CcspTraceNotice(("FEATURE_MAPT: MAP-T configuration cleared\n")); return RETURN_OK; @@ -2652,3 +2713,55 @@ ANSC_STATUS WanManager_get_interface_mac(char *interfaceName, char* macAddress, return returnStatus; } + +//Send and receive RS +int WanManager_send_and_receive_rs(DML_VIRTUAL_IFACE * p_VirtIf) +{ + struct in6_addr addr; + int ret = -1; + char command[256]; + char buffer[512]; + FILE *fp; + + CcspTraceInfo(("%s %d: Requesting Router solicit for %s \n", __FUNCTION__, __LINE__, p_VirtIf->Name)); + // Prepare the command to execute rdisc6 on the specified interface + snprintf(command, sizeof(command), "rdisc6 %s", p_VirtIf->Name ); + + // Execute the command and open a pipe to read its output + if ((fp = popen(command, "r")) == NULL) + { + perror("popen"); + return -1; + } + + // Read the output line by line + while (fgets(buffer, sizeof(buffer), fp) != NULL) + { + if (strstr(buffer, "Route lifetime")) + { + sscanf(buffer, " Route lifetime : %d", &p_VirtIf->IP.Ipv6Route.defRouteLifeTime); + } + + // Look for the "from" line to identify the default route address + if (strstr(buffer, "from")) + { + sscanf(buffer, " from %s", p_VirtIf->IP.Ipv6Route.defaultRoute); + if (inet_pton(AF_INET6, p_VirtIf->IP.Ipv6Route.defaultRoute, &addr) == 1) //check parsed value is a valid ipv6 address + { + ret = 0; + break; + } + } + } + + // Close the pipe + pclose(fp); + + if(ret == 0) + { + CcspTraceInfo(("%s %d: Received Router Advertisement with default route %s lifetime %d\n", __FUNCTION__, __LINE__, p_VirtIf->IP.Ipv6Route.defaultRoute, p_VirtIf->IP.Ipv6Route.defRouteLifeTime)); + } + + return ret; +} + diff --git a/source/WanManager/wanmgr_net_utils.h b/source/WanManager/wanmgr_net_utils.h index 9d5ee78..0ae5bc0 100644 --- a/source/WanManager/wanmgr_net_utils.h +++ b/source/WanManager/wanmgr_net_utils.h @@ -256,4 +256,5 @@ void WanManager_PrintBootEvents (WanBootEventState state); BOOL IsValidIpAddress(int32_t af, const char *address); +int WanManager_send_and_receive_rs(DML_VIRTUAL_IFACE * pVirtIf); #endif // _WANMGR_NET_UTILS_H_ diff --git a/source/WanManager/wanmgr_policy_auto_impl.c b/source/WanManager/wanmgr_policy_auto_impl.c index c6e9bab..8181654 100644 --- a/source/WanManager/wanmgr_policy_auto_impl.c +++ b/source/WanManager/wanmgr_policy_auto_impl.c @@ -710,8 +710,11 @@ static WcAwPolicyState_t Transition_TryingNextInterface (WanMgr_Policy_Controlle if (pWanIfaceGroup != NULL) { //All interfaces are scanned atleast once. set InitialScanComplete to TRUE - pWanIfaceGroup->InitialScanComplete = TRUE; - CcspTraceInfo(("%s %d group(%d) Initial Scan Completed\n", __FUNCTION__, __LINE__, pWanController->GroupInst)); + if(pWanIfaceGroup->InitialScanComplete == FALSE) + { + pWanIfaceGroup->InitialScanComplete = TRUE; + CcspTraceInfo(("%s %d group(%d) Initial Scan Completed\n", __FUNCTION__, __LINE__, pWanController->GroupInst)); + } WanMgrDml_GetIfaceGroup_release(); } @@ -1176,8 +1179,8 @@ static WcAwPolicyState_t State_ScanningInterface (WanMgr_Policy_Controller_t * p } - //If PHY is down ,rollback to waiting state after all VISM are terminated. - if(pActiveInterface->BaseInterfaceStatus != WAN_IFACE_PHY_STATUS_UP && WanMgr_Get_ISM_RunningStatus(pWanController->activeInterfaceIdx) == FALSE) + //Rollback to waiting state after all VISM are terminated. This could happen if PHY status changes when Interface is in scanning state. + if(WanMgr_Get_ISM_RunningStatus(pWanController->activeInterfaceIdx) == FALSE) { CcspTraceInfo(("%s %d: selected interface index:%d is BaseInetrfaceStatus DOWN. \n", __FUNCTION__, __LINE__, pWanController->activeInterfaceIdx )); return Transition_ScanningInterfaceDown(pWanController); diff --git a/source/WanManager/wanmgr_sysevents.c b/source/WanManager/wanmgr_sysevents.c index f924df3..4b368f3 100644 --- a/source/WanManager/wanmgr_sysevents.c +++ b/source/WanManager/wanmgr_sysevents.c @@ -1145,35 +1145,6 @@ static int CheckV6DefaultRule (char *wanInterface) return ret; } -static int do_toggle_v6_status (void) -{ - int ret = 0; - -#ifdef FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE - char wanInterface[BUFLEN_64] = {'\0'}; - wanmgr_get_wan_interface(wanInterface); -#else - char *wanInterface = "erouter0"; -#endif - - if (CheckV6DefaultRule(wanInterface) != TRUE) - { - CcspTraceInfo(("%s %d toggle initiated\n", __FUNCTION__, __LINE__)); - - if (sysctl_iface_set("/proc/sys/net/ipv6/conf/%s/disable_ipv6", wanInterface, "1") != 0) - { - CcspTraceWarning(("%s-%d : Failure writing to /proc file\n", __FUNCTION__, __LINE__)); - } - - if (sysctl_iface_set("/proc/sys/net/ipv6/conf/%s/disable_ipv6", wanInterface, "0") != 0) - { - CcspTraceWarning(("%s-%d : Failure writing to /proc file\n", __FUNCTION__, __LINE__)); - } - } - - return ret; -} - /* * @brief Utility function used to toggle ipv6 triggered from ISM. * This function will not check existing default route. @@ -1194,26 +1165,28 @@ int Force_IPv6_toggle (char* wanInterface) { CcspTraceWarning(("%s-%d : Failure writing to /proc file\n", __FUNCTION__, __LINE__)); } + sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_IPV6_TOGGLE, "FALSE", 0); //Reset toggle flag to false. return ret; } -void wanmgr_Ipv6Toggle (void) +/* + * @brief Utility function used to check the default route and send router solicit if not available. + * @param : Virtual Interface Interface . + * @return Returns NONE. + */ +void WanMgr_CheckDefaultRA (DML_VIRTUAL_IFACE * pVirtIf) { char v6Toggle[BUFLEN_128] = {0}; -#if (defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) && !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE)//TODO: V6 handled in PAM - /*Ipv6 handled in PAM. No Toggle Needed. */ - return; -#endif - + //TODO : Move router monitor to a WanManager thread ? to avoid continous sysevent get sysevent_get(sysevent_fd, sysevent_token, SYSEVENT_IPV6_TOGGLE, v6Toggle, sizeof(v6Toggle)); if((strlen(v6Toggle) == 0) || (!strcmp(v6Toggle,"TRUE"))) { CcspTraceInfo(("%s %d SYSEVENT_IPV6_TOGGLE[TRUE] \n", __FUNCTION__, __LINE__)); - - if(do_toggle_v6_status() ==0) + //TODO: add check for remote device ( static ip ) + if (CheckV6DefaultRule(pVirtIf->Name) == TRUE || WanManager_send_and_receive_rs(pVirtIf) == 0) { sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_IPV6_TOGGLE, "FALSE", 0); } @@ -1221,7 +1194,7 @@ void wanmgr_Ipv6Toggle (void) } /* - * @brief Utility function used to Configure accept_ra from ISM. + * @brief Utility function used to Configure accept_ra_defrtr from ISM. * @param : Virtual Interface and Enable. * @return Returns NONE. */ @@ -1238,28 +1211,23 @@ void WanMgr_Configure_accept_ra(DML_VIRTUAL_IFACE * pVirtIf, BOOL EnableRa) } CcspTraceInfo(("%s %d %s accept_ra for interface %s\n", __FUNCTION__, __LINE__,EnableRa?"Enabling":"Disabling", pVirtIf->Name)); - + //Enable accept_ra to allow receiving RA all the time. This funtion only blocks learning defult route from RA. + v_secure_system("sysctl -w net.ipv6.conf.%s.accept_ra=2",pVirtIf->Name); if(EnableRa) { v_secure_system("sysctl -w net.ipv6.conf.%s.router_solicitations=3",pVirtIf->Name); - v_secure_system("sysctl -w net.ipv6.conf.%s.accept_ra=2",pVirtIf->Name); - - CcspTraceInfo(("%s %d Enabling forwarding for interface %s\n", __FUNCTION__, __LINE__,pVirtIf->Name)); v_secure_system("sysctl -w net.ipv6.conf.%s.forwarding=1",pVirtIf->Name); v_secure_system("sysctl -w net.ipv6.conf.%s.accept_ra_pinfo=0",pVirtIf->Name); - v_secure_system("sysctl -w net.ipv6.conf.%s.accept_ra_defrtr=1",pVirtIf->Name); + v_secure_system("sysctl -w net.ipv6.conf.%s.accept_ra_defrtr=1",pVirtIf->Name); //Learn defult route from the RA. v_secure_system("sysctl -w net.ipv6.conf.all.forwarding=1"); - CcspTraceInfo(("%s %d IPv6 toggle after ra accept \n", __FUNCTION__, __LINE__)); -#if !defined (_PLATFORM_RASPBERRYPI_) //REFPLTB-3054 - Force_IPv6_toggle(pVirtIf->Name); // Do a IPv6 toggle to send Router Solicit -#endif + CcspTraceInfo(("%s %d Enabling forwarding for interface %s\n", __FUNCTION__, __LINE__,pVirtIf->Name)); } else { + //Only accept_ra_defrtr set to false to block setting default route. v_secure_system("sysctl -w net.ipv6.conf.%s.router_solicitations=0",pVirtIf->Name); - v_secure_system("sysctl -w net.ipv6.conf.%s.accept_ra=0",pVirtIf->Name); + v_secure_system("sysctl -w net.ipv6.conf.%s.accept_ra_defrtr=0",pVirtIf->Name); } - } static int getVendorClassInfo(char *buffer, int length) diff --git a/source/WanManager/wanmgr_sysevents.h b/source/WanManager/wanmgr_sysevents.h index ea894a0..0e856c5 100644 --- a/source/WanManager/wanmgr_sysevents.h +++ b/source/WanManager/wanmgr_sysevents.h @@ -295,7 +295,7 @@ INT wanmgr_isWanStandby(); * @brief Utility function used to toggle ipv6 based on sysevent from netmonitor. * @return Returns NONE. */ -void wanmgr_Ipv6Toggle(); +void WanMgr_CheckDefaultRA(DML_VIRTUAL_IFACE * pVirtIf); /* * @brief Utility function used to toggle ipv6 triggered from ISM. diff --git a/source/WanManager/wanmgr_wan_failover.c b/source/WanManager/wanmgr_wan_failover.c index 2a79fe8..07146ee 100644 --- a/source/WanManager/wanmgr_wan_failover.c +++ b/source/WanManager/wanmgr_wan_failover.c @@ -249,38 +249,6 @@ static ANSC_STATUS WanMgr_ActivateGroup(UINT groupId) return ANSC_STATUS_SUCCESS; } -#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) -/* WanMgr_SetRestartV6Client() - * Trigger the selected interface to restart IPv6 client - */ -//TODO: This is a workaround for the platforms using PAM for configuring Ipv6 -static ANSC_STATUS WanMgr_SetRestartV6Client(UINT groupId) -{ - - WANMGR_IFACE_GROUP* pWanIfaceGroup = WanMgr_GetIfaceGroup_locked((groupId - 1)); - if (pWanIfaceGroup != NULL) - { - if (pWanIfaceGroup->SelectedInterface) - { - WanMgr_Iface_Data_t* pWanDmlIfaceData = WanMgr_GetIfaceData_locked((pWanIfaceGroup->SelectedInterface - 1)); - if (pWanDmlIfaceData != NULL) - { - DML_WAN_IFACE* pWanIfaceData = &(pWanDmlIfaceData->data); - if(pWanIfaceData->VirtIfList->IP.IPv6Source == DML_WAN_IP_SOURCE_DHCP) - { - CcspTraceInfo(("%s %d Triggering RestartV6Client for %s \n", __FUNCTION__, __LINE__, pWanIfaceData->VirtIfList->Name)); - pWanIfaceData->VirtIfList->IP.RestartV6Client =TRUE; - } - WanMgrDml_GetIfaceData_release(pWanDmlIfaceData); - } - } - WanMgrDml_GetIfaceGroup_release(); - } - - return ANSC_STATUS_SUCCESS; -} -#endif - static void WanMgr_FO_IfaceGroupMonitor() { for(int i = 0; i < WanMgr_GetTotalNoOfGroups(); i++) @@ -590,9 +558,6 @@ static WcFailOverState_t Transition_ActivateGroup (WanMgr_FailOver_Controller_t //Update Telemetry if(pFailOverController->CurrentActiveGroup) { -#if !defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) - WanMgr_SetRestartV6Client(pFailOverController->CurrentActiveGroup); -#endif if(pFailOverController->CurrentActiveGroup < pFailOverController->HighestValidGroup) pFailOverController->TelemetryEvent = WAN_FAILOVER_SUCCESS; else if(pFailOverController->CurrentActiveGroup > pFailOverController->HighestValidGroup)