diff --git a/source/TR-181/include/wanmgr_dml.h b/source/TR-181/include/wanmgr_dml.h index b52f6db1..9897dc3f 100644 --- a/source/TR-181/include/wanmgr_dml.h +++ b/source/TR-181/include/wanmgr_dml.h @@ -366,14 +366,12 @@ typedef struct _WANMGR_IPV6_DATA uint32_t prefixVltime; char sitePrefixOld[BUFLEN_48]; /**< add support for RFC7084 requirement L-13 */ uint32_t ipv6_TimeOffset; - #if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) /* Params to store the IPv6 IPC message */ - bool addrAssigned; + bool addrAssigned; /**< Have we been assigned an IPv6 address ? */ uint32_t addrCmd; - bool prefixAssigned; /**< Have we been assigned a site prefix ? */ + bool prefixAssigned; /**< Have we been assigned a site prefix ? */ uint32_t prefixCmd; bool domainNameAssigned; /**< Have we been assigned dns server addresses ? */ - #endif } WANMGR_IPV6_DATA; typedef struct _WANMGR_IPV6_RA_DATA diff --git a/source/TR-181/middle_layer_src/wanmgr_rdkbus_common.h b/source/TR-181/middle_layer_src/wanmgr_rdkbus_common.h index 9abbff8f..7e437816 100644 --- a/source/TR-181/middle_layer_src/wanmgr_rdkbus_common.h +++ b/source/TR-181/middle_layer_src/wanmgr_rdkbus_common.h @@ -90,7 +90,6 @@ typedef struct _CONTEXT_LINK_OBJECT #define DML_ALIAS_NAME_LENGTH 64 #define DML_DHCP_CLIENT_IFNAME "erouter0" -#define CFG_TR181_DHCPv6_SERVER_IfName "brlan0" ANSC_STATUS SListPushEntryByInsNum (PSLIST_HEADER pListHead, PCONTEXT_LINK_OBJECT pLinkContext); diff --git a/source/WanManager/DHCPv6cMsgHandler/dhcpv6c_msg_apis.c b/source/WanManager/DHCPv6cMsgHandler/dhcpv6c_msg_apis.c index 75e5e2ac..f2558db5 100644 --- a/source/WanManager/DHCPv6cMsgHandler/dhcpv6c_msg_apis.c +++ b/source/WanManager/DHCPv6cMsgHandler/dhcpv6c_msg_apis.c @@ -733,14 +733,19 @@ static void * WanMgr_DhcpV6MsgHandler() 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)); - + // Set prefixAssigned to TRUE only if both preferred and valid lifetimes are positive + if (dhcpv6_data.prefixPltime > 0 && dhcpv6_data.prefixVltime > 0) + { + dhcpv6_data.prefixAssigned = TRUE; + } else { + dhcpv6_data.prefixAssigned = FALSE; + } //IPv6 prefix related sysevents // Define the eventMaps array as before Ipv6SyseventMap eventMaps[] = { diff --git a/source/WanManager/wanmgr_dhcp_event_handler.c b/source/WanManager/wanmgr_dhcp_event_handler.c index e7420954..a5b18e5b 100644 --- a/source/WanManager/wanmgr_dhcp_event_handler.c +++ b/source/WanManager/wanmgr_dhcp_event_handler.c @@ -104,6 +104,17 @@ static void copyDhcpv6Data(WANMGR_IPV6_DATA* pDhcpv6Data, const DHCP_MGR_IPV6_MS pDhcpv6Data->prefixAssigned = leaseInfo->prefixAssigned; pDhcpv6Data->domainNameAssigned = leaseInfo->domainNameAssigned; pDhcpv6Data->ipv6_TimeOffset = leaseInfo->ipv6_TimeOffset; + if(!pDhcpv6Data->addrAssigned && pDhcpv6Data->prefixAssigned) + { + /* In an IPv6 lease, if only IAPD is received and we never received IANA, + * We can use the received IAPD to construct a Ipv6 /128 address which can be used for managerment and voice ... + * If we reach this point, only IAPD has been received. Calculate Wan Ipv6 address + */ + + CcspTraceInfo(("IANA is not assigned by DHCPV6. Constructing WAN address from the IAPD for Wan Interface \n")); + wanmgr_construct_wan_address_from_IAPD(pDhcpv6Data); + } + } /* @@ -209,7 +220,7 @@ void WanMgr_ProcessDhcpClientEvent(DhcpEventThreadArgs *eventData) //TODO: Check for sysevents if(pVirtIf->IP.Ipv6Data.prefixAssigned == TRUE) { - WanManager_Ipv6PrefixUtil(pVirtIf->Name, SET_LFT, pVirtIf->IP.Ipv6Data.prefixPltime, pVirtIf->IP.Ipv6Data.prefixVltime); + WanManager_Ipv6AddrUtil(pVirtIf, SET_LFT); sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_RADVD_RESTART, NULL, 0); } CcspTraceInfo(("%s-%d : DHCPv6 lease renewed for %s\n", __FUNCTION__, __LINE__, pVirtIf->Name)); diff --git a/source/WanManager/wanmgr_dhcpv6_apis.c b/source/WanManager/wanmgr_dhcpv6_apis.c index a8084531..0d0dd5c0 100644 --- a/source/WanManager/wanmgr_dhcpv6_apis.c +++ b/source/WanManager/wanmgr_dhcpv6_apis.c @@ -53,10 +53,8 @@ extern char g_Subsystem[32]; #endif #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 static struct { pthread_t dhcpv6c_thread; @@ -1405,9 +1403,14 @@ WanMgr_DmlDhcpv6Remove(ANSC_HANDLE hContext) return; } -#if defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE) - /* dhcpv6_assign_global_ip Copied from PAM module */ -int dhcpv6_assign_global_ip(char * prefix, char * intfName, char * ipAddr) +/** +@brief Generates a full IPv6 address in EUI-64 format from a delegated prefix. +@param prefix The delegated IPv6 prefix. +@param intfName The name of the network interface. +@param ipAddr The buffer to store the generated IPv6 address. +@return int 0 on success, non-zero on failure. +*/ +static int WanMgr_create_eui64_ipv6_address(char * prefix, char * intfName, char * ipAddr) { unsigned int length = 0; @@ -1447,28 +1450,6 @@ int dhcpv6_assign_global_ip(char * prefix, char * intfName, char * ipAddr) CcspTraceError(("error, there is not '::' in prefix:%s\n", prefix)); return 1; } -#if defined(_HUB4_PRODUCT_REQ_) || defined(_RDKB_GLOBAL_PRODUCT_REQ_) -#if defined(_RDKB_GLOBAL_PRODUCT_REQ_) - WanMgr_Config_Data_t *pWanConfigData = WanMgr_GetConfigData_locked(); - unsigned char IPv6EUI64FormatSupport = TRUE; - - if( NULL != pWanConfigData ) - { - IPv6EUI64FormatSupport = pWanConfigData->data.IPv6EUI64FormatSupport; - WanMgrDml_GetConfigData_release(pWanConfigData); - } - - if ( FALSE == IPv6EUI64FormatSupport ) -#endif /** _RDKB_GLOBAL_PRODUCT_REQ_ */ - { - if(strncmp(intfName, COSA_DML_DHCPV6_SERVER_IFNAME, strlen(intfName)) == 0) - { - snprintf(ipAddr, 128, "%s1", globalIP); - CcspTraceInfo(("the full part is:%s\n", ipAddr)); - return 0; - } - } -#endif j = i-2; k = 0; @@ -1487,6 +1468,7 @@ int dhcpv6_assign_global_ip(char * prefix, char * intfName, char * ipAddr) CcspTraceInfo(("the first part is:%s\n", globalIP)); /* prepare second part */ + /* Step 1: Extract the MAC address of the specified network interface */ fp = v_secure_popen("r", "ifconfig %s | grep HWaddr", intfName ); _get_shell_output(fp, out, sizeof(out)); v_secure_pclose(fp); @@ -1499,6 +1481,7 @@ int dhcpv6_assign_global_ip(char * prefix, char * intfName, char * ipAddr) while( pMac && (pMac[0] == ' ') ) pMac++; + /* Step 2: Toggle the 7th bit of the first byte of the MAC address */ /* switch 7bit to 1*/ tmp[0] = pMac[1]; @@ -1513,12 +1496,14 @@ int dhcpv6_assign_global_ip(char * prefix, char * intfName, char * ipAddr) pMac[1] = k; pMac[17] = '\0'; + /* Step 3: Insert the "FF:FE" sequence in the middle of the MAC address */ //00:50:56: FF:FE: 92:00:22 _ansc_strncpy(out, pMac, 9); out[9] = '\0'; _ansc_strcat(out, "FF:FE:"); _ansc_strcat(out, pMac+9); + /* Step 4: Format the resulting string into the IPv6 address format */ for(k=0,j=0;out[j];j++){ if ( out[j] == ':' ) continue; @@ -1531,12 +1516,11 @@ int dhcpv6_assign_global_ip(char * prefix, char * intfName, char * ipAddr) globalIP[i-1] = '\0'; - CcspTraceInfo(("the full part is:%s\n", globalIP)); + CcspTraceInfo(("The generated Ip v6 address for interface %s is:%s\n",intfName, globalIP)); _ansc_strncpy(ipAddr, globalIP, sizeof(globalIP) - 1); /* This IP should be unique. If not I have no idea. */ return 0; } -#endif static ANSC_STATUS wanmgr_dchpv6_get_ipc_msg_info(WANMGR_IPV6_DATA* pDhcpv6Data, ipc_dhcpv6_data_t* pIpcIpv6Data) { @@ -1592,6 +1576,137 @@ static int WanMgr_CopyPreviousPrefix(WANMGR_IPV6_DATA* pOld, WANMGR_IPV6_DATA* p } #endif +/** + * @brief Constructs a WAN IPv6 address from the received IAPD (IA Prefix Delegation). + * + * This function derives a /128 host address for the WAN interface from the first /64 subnet + * of the delegated prefix — the same /64 used by LAN clients. This is compliant with: + * + * - RFC 7084 Section 4.2 WAA-7: CE router MUST create a global IPv6 address from its + * delegated prefix(es) if no address is acquired via SLAAC or DHCPv6. + * - RFC 9096 Section 3.3 & 3.5: Addresses derived from delegated prefixes should follow + * prefix lifetime management; using the same /64 avoids wasting subnets and aligns with + * the renumbering expectations defined in RFC 9096. + * - RFC 4862 Section 5.4: Duplicate Address Detection (DAD) is mandatory for all unicast + * addresses, providing a protocol-level safeguard against any theoretical collision. + * + * The WAN /128 host address does not conflict with LAN clients because: + * - In EUI-64 mode: the IID is derived from the WAN interface MAC, which is unique per interface. + * - In non-EUI-64 mode: the well-known suffix ::1 is used. SLAAC EUI-64 clients cannot + * generate ::1 (derived from their own MACs), and the LAN-side DHCPv6 server can exclude + * this address from its assignable pool. + * + * @param[in] pIpv6DataNew Pointer to the WANMGR_IPV6_DATA structure containing IAPD info. + * + * @return + * - 0 on success. + * - -1 on failure (e.g., invalid prefix format, prefix length > 64, or system command failure). + * + * ### Example: + * Given an IAPD of "2a06:5906:13:d000::/56": + * - LAN IPv6 Range: "2a06:5906:13:d000::/64" + * - WAN IPv6 (EUI-64): "2a06:5906:13:d000:a8bb:ccff:fedd:eeff/128" (from WAN MAC) + * - WAN IPv6 (suffix): "2a06:5906:13:d000::1/128" + * + * Given an IAPD of "2a06:5906:13:d000::/64" (single /64 delegation): + * - LAN + WAN share the same /64 + * - WAN IPv6 (suffix): "2a06:5906:13:d000::1/128" + */ +#define WAN_SUFFIX 1 +int wanmgr_construct_wan_address_from_IAPD(WANMGR_IPV6_DATA *pIpv6DataNew) +{ + int prefix_length; + char iapd_prefix[128] = {0}; + char cmdLine[256] = {0}; + if (sscanf(pIpv6DataNew->sitePrefix, "%[^/]/%d", iapd_prefix, &prefix_length) != 2) + { + return -1; // Parsing failed + } + + if ( prefix_length > 64) + { + CcspTraceError(("%s %d Prefix length is > 64. Cannot derive a /64 subnet for address assignment\n", __FUNCTION__, __LINE__)); + return -1; + } + + struct in6_addr prefix; + // Convert prefix to binary format + if (inet_pton(AF_INET6, iapd_prefix, &prefix) != 1) + { + CcspTraceError(("%s %d Failed to convert prefix to in6_addr\n", __FUNCTION__, __LINE__)); + return -1; + } + + /* Use the first /64 subnet directly for WAN address (same /64 as LAN). + * RFC 7084 WAA-7 mandates deriving an address from the delegated prefix. + * RFC 9096 Section 3.3 expects addresses to track prefix lifetimes. + * A /128 host address on a separate interface (WAN) does not claim the /64; + * DAD (RFC 4862 Section 5.4) provides collision protection at zero cost. */ + + WanMgr_Config_Data_t *pWanConfigData = WanMgr_GetConfigData_locked(); + unsigned char IPv6EUI64FormatSupport = TRUE; + if( NULL != pWanConfigData ) + { + IPv6EUI64FormatSupport = pWanConfigData->data.IPv6EUI64FormatSupport; + WanMgrDml_GetConfigData_release(pWanConfigData); + } + + if(IPv6EUI64FormatSupport) + { + /* EUI-64: IID derived from WAN interface MAC — deterministically unique per interface. + * No collision possible with LAN clients (different MACs produce different IIDs). */ + char prefStr[128] = {0}; + inet_ntop(AF_INET6, &prefix, prefStr, sizeof(prefStr)); + CcspTraceInfo(("%s %d EUI64 format is enabled, using prefix %s for WAN address\n", __FUNCTION__, __LINE__, prefStr)); + snprintf(cmdLine, sizeof(cmdLine), "%s/%d", prefStr, prefix_length); + WanMgr_create_eui64_ipv6_address(cmdLine, pIpv6DataNew->ifname, pIpv6DataNew->address); + } + else + { + /* Non-EUI-64: Use well-known suffix ::1 (mirrors IPv4 gateway convention). + * SLAAC EUI-64 clients never generate ::1; DHCPv6 server should exclude ::1 from pool. */ + CcspTraceInfo(("%s %d EUI64 format is not enabled, using WAN_SUFFIX %d\n", __FUNCTION__, __LINE__, WAN_SUFFIX)); + prefix.s6_addr[15] = WAN_SUFFIX; + inet_ntop(AF_INET6, &prefix, pIpv6DataNew->address, sizeof(pIpv6DataNew->address)); + } + + pIpv6DataNew->addrAssigned = true; + pIpv6DataNew->addrCmd = IFADDRCONF_ADD; + + CcspTraceInfo(("%s %d Calculated WAN address %s/128\n", __FUNCTION__, __LINE__, pIpv6DataNew->address)); + // Assign the /128 host address on the WAN interface + memset(cmdLine, 0, sizeof(cmdLine)); + snprintf(cmdLine, sizeof(cmdLine), "ip -6 addr add %s/128 dev %s", pIpv6DataNew->address, pIpv6DataNew->ifname); + if (WanManager_DoSystemActionWithStatus(__FUNCTION__, cmdLine) != 0) + CcspTraceError(("failed to run cmd: %s", cmdLine)); + + /* Enable NDP proxy on the LAN bridge so the kernel responds to Neighbor Solicitations + * for the WAN address on brlan0. This ensures: + * - LAN clients performing DAD for this address will get a Neighbor Advertisement back, + * causing their DAD to fail (preventing them from using the WAN address). */ + memset(cmdLine, 0, sizeof(cmdLine)); + snprintf(cmdLine, sizeof(cmdLine), "sysctl -w net.ipv6.conf.%s.proxy_ndp=1", COSA_DML_DHCPV6_SERVER_IFNAME); + WanManager_DoSystemActionWithStatus(__FUNCTION__, cmdLine); + + /* Add NDP proxy entry for the WAN address on the LAN bridge. + * This makes the kernel respond to Neighbor Solicitations for our WAN address + * on brlan0, which: + * 1. Enables upstream routing to reach the WAN address via the LAN bridge if needed. + * 2. Causes DAD to fail for any LAN client that tries to use this address. */ + memset(cmdLine, 0, sizeof(cmdLine)); + snprintf(cmdLine, sizeof(cmdLine), "ip -6 neigh add proxy %s dev %s", pIpv6DataNew->address, COSA_DML_DHCPV6_SERVER_IFNAME); + if (WanManager_DoSystemActionWithStatus(__FUNCTION__, cmdLine) != 0) + CcspTraceError(("%s %d failed to add NDP proxy entry on %s for %s\n", __FUNCTION__, __LINE__, COSA_DML_DHCPV6_SERVER_IFNAME, pIpv6DataNew->address)); + + memset(cmdLine, 0, sizeof(cmdLine)); + snprintf(cmdLine, sizeof(cmdLine), COSA_DML_WANIface_ADDR_SYSEVENT_NAME , pIpv6DataNew->ifname); + CcspTraceInfo(("Setting sysevent: %s = %s\n", cmdLine, pIpv6DataNew->address)); + sysevent_set(sysevent_fd, sysevent_token, cmdLine, pIpv6DataNew->address, 0); + + return 0; +} + + ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) { if(NULL == pVirtIf) @@ -1664,7 +1779,8 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) /* 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. */ + * 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)); @@ -1672,6 +1788,18 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) pNewIpcMsg->addrAssigned = true; Ipv6DataNew.addrCmd = pDhcp6cInfoCur->addrCmd; } + else if(Ipv6DataNew.prefixAssigned) + { + /* In an IPv6 lease, if only IAPD is received and we never received IANA, + * We can use the received IAPD to construct a Ipv6 /128 address which can be used for managerment and voice ... + * If we reach this point, only IAPD has been received. Canculate Wan Ipv6 address + */ + + CcspTraceInfo(("IANA is not assigned by DHCPV6. Constructing WAN address from the IAPD for Wan Interface \n")); + wanmgr_construct_wan_address_from_IAPD(&Ipv6DataNew); + pNewIpcMsg->addrAssigned = true; + } + /* dhcp6c receives prefix delegation for LAN */ if (pNewIpcMsg->prefixAssigned && !IS_EMPTY_STRING(pNewIpcMsg->sitePrefix)) @@ -1873,29 +2001,8 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) { if(pVirtIf->Status == WAN_IFACE_STATUS_UP && pNewIpcMsg->prefixPltime > 0 && pNewIpcMsg->prefixVltime > 0 ) //Update life time only if the interface is active. { -#if !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) || defined(_RDKB_GLOBAL_PRODUCT_REQ_) //Do not add prefix on LAN bridge for the Comcast platforms. -#if defined(_RDKB_GLOBAL_PRODUCT_REQ_) - WanMgr_Config_Data_t *pWanConfigData = WanMgr_GetConfigData_locked(); - unsigned char ConfigureWANIPv6OnLANBridgeSupport = FALSE; - - if( NULL != pWanConfigData ) - { - ConfigureWANIPv6OnLANBridgeSupport = pWanConfigData->data.ConfigureWANIPv6OnLANBridgeSupport; - WanMgrDml_GetConfigData_release(pWanConfigData); - } - - if ( TRUE == ConfigureWANIPv6OnLANBridgeSupport ) -#endif /** _RDKB_GLOBAL_PRODUCT_REQ_ */ - { - //call function for changing the prlft and vallft - if ((WanManager_Ipv6PrefixUtil(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 @@ -1952,6 +2059,14 @@ ANSC_STATUS wanmgr_handle_dhcpv6_event_data(DML_VIRTUAL_IFACE * pVirtIf) return ANSC_STATUS_SUCCESS; } /* End of ProcessDhcp6cStateChanged() */ +/** + * @brief Sets up the IPv6 /128 address for the LAN bridge. + * This function creates an IPv6 /128 address for the LAN bridge, + * configures all necessary system events for the IPv6 LAN, + * and restarts the DHCPv6 server and RA server if required. + * @param pVirtIf Pointer to the virtual interface structure. + * @return int 0 on success, non-zero on failure. + */ int setUpLanPrefixIPv6(DML_VIRTUAL_IFACE* pVirtIf) { if (pVirtIf == NULL) @@ -2020,27 +2135,22 @@ int setUpLanPrefixIPv6(DML_VIRTUAL_IFACE* pVirtIf) if (pVirtIf->IP.Ipv6Data.prefixPltime != 0 && pVirtIf->IP.Ipv6Data.prefixVltime != 0) { - ret = dhcpv6_assign_global_ip(pVirtIf->IP.Ipv6Data.sitePrefix, COSA_DML_DHCPV6_SERVER_IFNAME, globalIP); + //Create a global IP for the LAN bridge from the received delegated prefix. + ret = WanMgr_create_eui64_ipv6_address(pVirtIf->IP.Ipv6Data.sitePrefix, COSA_DML_DHCPV6_SERVER_IFNAME, globalIP); if(ret != 0) { CcspTraceInfo(("Assign global ip error \n")); } 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)); -#endif - CcspTraceInfo(("%s lan_ipaddr_v6 set to [%s] \n", __FUNCTION__, globalIP)); + snprintf(pVirtIf->IP.Ipv6Data.pdIfAddress, sizeof(pVirtIf->IP.Ipv6Data.pdIfAddress), "%s/64", 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. + sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_FIELD_TR_BRLAN0_DHCPV6_SERVER_ADDRESS, globalIP, 0); + CcspTraceInfo(("%s lan_ipaddr_v6 set to [%s] \n", __FUNCTION__, globalIP)); } 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); @@ -2087,11 +2197,12 @@ int setUpLanPrefixIPv6(DML_VIRTUAL_IFACE* pVirtIf) int index = strcspn(pVirtIf->IP.Ipv6Data.sitePrefix, "/"); if (index < strlen(pVirtIf->IP.Ipv6Data.sitePrefix) && index < sizeof(prefix)) { - strncpy(prefix, pVirtIf->IP.Ipv6Data.sitePrefix, index); // only copy prefix without the prefix length - snprintf(set_value, sizeof(set_value), "%s1", prefix); // concatenate "1" onto the prefix, which is in the form "xxxx:xxxx:xxxx:xxxx::" - snprintf(pVirtIf->IP.Ipv6Data.pdIfAddress, sizeof(pVirtIf->IP.Ipv6Data.pdIfAddress), "%s/64", set_value); // concatenate prefix address with length "/64" - syscfg_set_string(SYSCFG_FIELD_IPV6_PREFIX_ADDRESS, pVirtIf->IP.Ipv6Data.pdIfAddress); - sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_FIELD_TR_BRLAN0_DHCPV6_SERVER_ADDRESS, set_value, 0); + strncpy(prefix, pVirtIf->IP.Ipv6Data.sitePrefix, index); // only copy prefix without the prefix length + // Create and set IPv6 address with /128 prefix length //TODO: SYSCFG_FIELD_IPV6_PREFIX_ADDRESS may not be used anymore. Check and remove if not used in the NTP script + char ipv6_addr_with_prefix[BUFLEN_64] = {0}; + snprintf(ipv6_addr_with_prefix, sizeof(ipv6_addr_with_prefix), "%s/128", pVirtIf->IP.Ipv6Data.address); + syscfg_set_string(SYSCFG_FIELD_IPV6_PREFIX_ADDRESS, ipv6_addr_with_prefix); + CcspTraceInfo(("%s %d IPv6 address syscfg %s set to %s\n", __FUNCTION__, __LINE__, SYSCFG_FIELD_IPV6_PREFIX_ADDRESS, ipv6_addr_with_prefix)); CcspTraceInfo(("%s %d new prefix = %s\n", __FUNCTION__, __LINE__, pVirtIf->IP.Ipv6Data.sitePrefix)); #if defined(CISCO_CONFIG_DHCPV6_PREFIX_DELEGATION) /* Use the delegated prefix length directly for platforms that support prefix delegation to LAN clients */ diff --git a/source/WanManager/wanmgr_dhcpv6_apis.h b/source/WanManager/wanmgr_dhcpv6_apis.h index ec591e69..bcc262db 100644 --- a/source/WanManager/wanmgr_dhcpv6_apis.h +++ b/source/WanManager/wanmgr_dhcpv6_apis.h @@ -49,7 +49,7 @@ #define ULOGF #endif -#define COSA_DML_DHCPV6_SERVER_IFNAME CFG_TR181_DHCPv6_SERVER_IfName +#define COSA_DML_DHCPV6_SERVER_IFNAME "brlan0" #define COSA_DML_DHCPV6C_PREF_SYSEVENT_NAME "tr_"DML_DHCP_CLIENT_IFNAME"_dhcpv6_client_v6pref" #define COSA_DML_DHCPV6C_PREF_IAID_SYSEVENT_NAME "tr_"DML_DHCP_CLIENT_IFNAME"_dhcpv6_client_pref_iaid" @@ -353,6 +353,31 @@ void _get_shell_output(FILE *fp, char * out, int len); ************************************************************************************/ int setUpLanPrefixIPv6(DML_VIRTUAL_IFACE* pVirtIf); +/** + * @brief Constructs a dedicated WAN IPv6 address from the received IAPD (IA Prefix Delegation). + * + * This function extracts the IPv6 prefix and its length from the given IAPD data. It then uses + * the provided prefix to construct a unique WAN IPv6 address by using the next available /64 subnet. + * The first /64 subnet of the IAPD is reserved for LAN, while the next /64 is used for the WAN address. + * The constructed WAN address is assigned to the specified WAN interface. + * + * @param[in] pIpv6DataNew Pointer to the WANMGR_IPV6_DATA structure. + * + * @return + * - 0 on success. + * - -1 on failure (e.g., invalid prefix format, prefix length >= 64, or system command failure). + * + * @note The function assumes that if the prefix length is less than 64, there are sufficient bits available + * to split the IAPD into multiple /64 subnets. If the prefix length is 64 or greater, it logs an error + * and returns -1 since further subnetting is not possible. + * + * ### Example: + * Given an IAPD of "2a06:5906:13:d000::/56", the function may construct the following addresses: + * - LAN IPv6 Address Range: "2a06:5906:13:d000::/64" + * - WAN IPv6 Address: "2a06:5906:13:d001::1/128" + */ +int wanmgr_construct_wan_address_from_IAPD(WANMGR_IPV6_DATA *pIpv6DataNew); + ANSC_STATUS WanMgr_Handle_Dhcpv6_NetLink_Address_Event(IPv6NetLinkAddrEvent *pstAddrEvent); #endif //_WANMGR_DHCPV6_APIS_H_ diff --git a/source/WanManager/wanmgr_interface_sm.c b/source/WanManager/wanmgr_interface_sm.c index c2e42a03..d0705b7b 100644 --- a/source/WanManager/wanmgr_interface_sm.c +++ b/source/WanManager/wanmgr_interface_sm.c @@ -59,9 +59,6 @@ #define POSTD_START_FILE "/tmp/.postd_started" #define SELECTED_MODE_TIMEOUT_SECONDS 10 -#if defined(FEATURE_IPOE_HEALTH_CHECK) && defined(IPOE_HEALTH_CHECK_LAN_SYNC_SUPPORT) -extern lanState_t lanState; -#endif #if defined(FEATURE_464XLAT) typedef enum @@ -198,7 +195,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 checkIpv6LanAddressIsReadyToUse(DML_VIRTUAL_IFACE* p_VirtIf); +static int checkIpv6AddressIsReadyToUse(DML_VIRTUAL_IFACE* p_VirtIf); #ifdef FEATURE_MAPE /************************************************************************************* @@ -1035,57 +1032,37 @@ int wan_updateDNS(WanMgr_IfaceSM_Controller_t* pWanIfaceCtrl, BOOL addIPv4, BOOL return ret; } -/* 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. + +/** + * @brief Checks if the IPv6 address is ready to use. + * + * This function checks the tentative address, detects Duplicate Address Detection (DAD) failure, and verifies the default route. + * If DAD fails, it also triggers a Router Solicitation. + * + * @param p_VirtIf Pointer to the virtual interface structure. + * @return int 0 on success, negative value on failure. */ -static int checkIpv6LanAddressIsReadyToUse(DML_VIRTUAL_IFACE* p_VirtIf) +static int checkIpv6AddressIsReadyToUse(DML_VIRTUAL_IFACE* p_VirtIf) { char buffer[BUFLEN_256] = {0}; - FILE *fp_dad = NULL; - FILE *fp_route = NULL; + FILE *fp_dad = NULL; + FILE *fp_route = NULL; int dad_flag = 0; int route_flag = 0; - int i; - char IfaceName[BUFLEN_16] = {0}; - int BridgeMode = 0; - { //TODO : temporary debug code to identify the bridgemode sysevent failure issue. - char Output[BUFLEN_16] = {0}; - if (sysevent_get(sysevent_fd, sysevent_token, "bridge_mode", Output, sizeof(Output)) !=0) - { - CcspTraceError(("%s-%d: bridge_mode sysevent get failed. \n", __FUNCTION__, __LINE__)); - } - BridgeMode = atoi(Output); - CcspTraceInfo(("%s-%d: <> bridge_mode sysevent value set to =%d \n", __FUNCTION__, __LINE__, BridgeMode)); - } - /*TODO: - *Below Code should be removed once V6 Prefix/IP is assigned on erouter0 Instead of brlan0 for sky Devices. - */ - strncpy(IfaceName, ETH_BRIDGE_NAME, sizeof(IfaceName)-1); - if (WanMgr_isBridgeModeEnabled() == TRUE) - { - CcspTraceInfo(("%s-%d: Device is in bridge mode. Assigning IPv6 address on WAN interface.\n", __FUNCTION__, __LINE__)); - memset(IfaceName, 0, sizeof(IfaceName)); - strncpy(IfaceName, p_VirtIf->Name, sizeof(IfaceName)-1); - } - CcspTraceInfo(("%s-%d: IfaceName=%s, BridgeMode=%d \n", __FUNCTION__, __LINE__, IfaceName, BridgeMode)); + /* 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. + */ + // Note: This check is not strictly necessary and this check could delay the WAN up by 15 seconds in worst case. If the IPv6 address (IANA) is obtained via DHCPv6, and the DHCP client already performs the DAD check. + // However, it is beneficial to verify that the WAN IPv6 address is auto-calculated from the delegated prefix or via SLAAC. - /* 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++) + for(int 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 = v_secure_popen("r","ip address show dev %s tentative", p_VirtIf->Name))) { if(fp_dad != NULL) { @@ -1098,7 +1075,6 @@ static int checkIpv6LanAddressIsReadyToUse(DML_VIRTUAL_IFACE* p_VirtIf) } } } - if(dad_flag == 0) { sleep(1); @@ -1122,10 +1098,10 @@ static int checkIpv6LanAddressIsReadyToUse(DML_VIRTUAL_IFACE* p_VirtIf) } } - //if DAD failed on LAN bridge, log an ERROR message and continue with the WAN process. + //if DAD failed on WAN interface, log an ERROR message and continue with the WAN process. if(dad_flag == 0 || route_flag == 0) { - CcspTraceError(("%s %d dad_flag[%d] route_flag[%d] Failed \n", __FUNCTION__, __LINE__,dad_flag,route_flag)); + CcspTraceError(("%s %d dad_flag[%s] route_flag[%s] Failed \n", __FUNCTION__, __LINE__, dad_flag ? "SUCCESS" : "FAILED", route_flag ? "SUCCESS" : "FAILED")); } if(route_flag == 0) @@ -1231,13 +1207,15 @@ static void updateInterfaceToVoiceManager(WanMgr_IfaceSM_Controller_t* pWanIface * @brief Removes IPv6 default route and global addresses from interface * * @param ifaceName Interface name (e.g., "eth0", "erouter0") + * @param ipv6Address The IPv6 address to remove NDP proxy for (can be NULL or empty) * @return RETURN_OK on success, RETURN_ERR on failure * * @note This API performs the following operations: * 1. Deletes IPv6 default route for the interface * 2. Flushes all global scope IPv6 addresses from the interface + * 3. Removes the NDP proxy entry for the WAN address from the LAN bridge */ -static int WanMgr_RemoveIPv6RouteAndAddress(const char* ifaceName) +static int WanMgr_RemoveIPv6RouteAndAddress(const char* ifaceName, const char* ipv6Address) { if (ifaceName == NULL || strlen(ifaceName) == 0) { @@ -1269,6 +1247,16 @@ static int WanMgr_RemoveIPv6RouteAndAddress(const char* ifaceName) ret = RETURN_ERR; } + /* Remove the specific NDP proxy entry for the WAN address from the LAN bridge. + * This was added by wanmgr_construct_wan_address_from_IAPD() to proxy the + * WAN /128 address on brlan0 for DAD protection and reachability. */ + if (ipv6Address != NULL && ipv6Address[0] != '\0') + { + memset(acCmdLine, 0, sizeof(acCmdLine)); + snprintf(acCmdLine, sizeof(acCmdLine), "ip -6 neigh del proxy %s dev %s", ipv6Address, COSA_DML_DHCPV6_SERVER_IFNAME); + WanManager_DoSystemActionWithStatus(__FUNCTION__, acCmdLine); + } + return ret; } @@ -1753,14 +1741,15 @@ static int wan_tearDownIPv6(WanMgr_IfaceSM_Controller_t * pWanIfaceCtrl) } } #endif + /** Unconfig IPv6. */ - if ( WanManager_Ipv6PrefixUtil(p_VirtIf->Name, DEL_ADDR,0,0) < 0) + if ( WanManager_Ipv6AddrUtil(p_VirtIf, DEL_ADDR) < 0) { AnscTraceError(("%s %d - Failed to remove inactive address \n", __FUNCTION__,__LINE__)); } /* Remove IPv6 default route and global addresses */ - if (WanMgr_RemoveIPv6RouteAndAddress(p_VirtIf->Name) != RETURN_OK) + if (WanMgr_RemoveIPv6RouteAndAddress(p_VirtIf->Name, p_VirtIf->IP.Ipv6Data.address) != RETURN_OK) { CcspTraceError(("%s %d - Failed to remove IPv6 route and address for '%s'\n", __FUNCTION__, __LINE__, p_VirtIf->Name)); @@ -1787,6 +1776,7 @@ static int wan_tearDownIPv6(WanMgr_IfaceSM_Controller_t * pWanIfaceCtrl) sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_FIREWALL_RESTART, NULL, 0); //RBUS_WAN_IP +//TODO : **************************** Check this ************************ #if defined (RBUS_WAN_IP) #if defined(_RDKB_GLOBAL_PRODUCT_REQ_) unsigned char ConfigureWANIPv6OnLANBridgeSupport = FALSE; @@ -1995,14 +1985,14 @@ static ANSC_STATUS WanMgr_SendMsgTo_ConnectivityCheck(WanMgr_IfaceSM_Controller_ //Restarting firewall to add IPOE_HEALTH_CHECK firewall rules. sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_FIREWALL_RESTART, NULL, 0); } - WanMgr_SendMsgToIHC(IPOE_MSG_WAN_CONNECTION_UP, p_VirtIf->Name); + WanMgr_SendMsgToIHC(IPOE_MSG_WAN_CONNECTION_UP, p_VirtIf); pWanIfaceCtrl->IhcV4Status = IHC_STARTED; } } else if(type == CONNECTION_MSG_IPV4 && ConnStatus == FALSE) { CcspTraceInfo(("%s %d Sending IPOE_MSG_WAN_CONNECTION_DOWN \n", __FUNCTION__, __LINE__)); - WanMgr_SendMsgToIHC(IPOE_MSG_WAN_CONNECTION_DOWN, p_VirtIf->Name); + WanMgr_SendMsgToIHC(IPOE_MSG_WAN_CONNECTION_DOWN, p_VirtIf); pWanIfaceCtrl->IhcV4Status = IHC_STOPPED; } else if(type == CONNECTION_MSG_IPV6 && ConnStatus == TRUE) @@ -2018,14 +2008,14 @@ static ANSC_STATUS WanMgr_SendMsgTo_ConnectivityCheck(WanMgr_IfaceSM_Controller_ //Restarting firewall to add IPOE_HEALTH_CHECK firewall rules. sysevent_set(sysevent_fd, sysevent_token, SYSEVENT_FIREWALL_RESTART, NULL, 0); } - WanMgr_SendMsgToIHC(IPOE_MSG_WAN_CONNECTION_IPV6_UP, p_VirtIf->Name); + WanMgr_SendMsgToIHC(IPOE_MSG_WAN_CONNECTION_IPV6_UP, p_VirtIf); pWanIfaceCtrl->IhcV6Status = IHC_STARTED; } } else if(type == CONNECTION_MSG_IPV6 && ConnStatus == FALSE) { CcspTraceInfo(("%s %d Sending IPOE_MSG_WAN_CONNECTION_IPV6_DOWN \n", __FUNCTION__, __LINE__)); - WanMgr_SendMsgToIHC(IPOE_MSG_WAN_CONNECTION_IPV6_DOWN, p_VirtIf->Name); + WanMgr_SendMsgToIHC(IPOE_MSG_WAN_CONNECTION_IPV6_DOWN, p_VirtIf); pWanIfaceCtrl->IhcV6Status = IHC_STOPPED; } @@ -2951,7 +2941,6 @@ static eWanState_t wan_transition_ipv6_down(WanMgr_IfaceSM_Controller_t* pWanIfa WanMgr_Rbus_EventPublishHandler(param_name, "", RBUS_STRING); snprintf(param_name, sizeof(param_name), "Device.X_RDK_WanManager.Interface.%d.VirtualInterface.%d.IP.IPv6Prefix", p_VirtIf->baseIfIdx+1, p_VirtIf->VirIfIdx+1); WanMgr_Rbus_EventPublishHandler(param_name, "", RBUS_STRING); - WanManager_UpdateInterfaceStatus (p_VirtIf, WANMGR_IFACE_CONNECTION_IPV6_DOWN); //Disable accept_ra WanMgr_Configure_accept_ra(p_VirtIf, FALSE); @@ -2965,7 +2954,7 @@ static eWanState_t wan_transition_ipv6_down(WanMgr_IfaceSM_Controller_t* pWanIfa if (WanMgr_IsVoiceInterface(p_VirtIf)) { /* Clean up IPv6 routes and addresses only */ - WanMgr_RemoveIPv6RouteAndAddress(p_VirtIf->Name); + WanMgr_RemoveIPv6RouteAndAddress(p_VirtIf->Name, p_VirtIf->IP.Ipv6Data.address); CcspTraceInfo(("%s %d - Voice interface '%s' IPv6 down - removing routes/addresses only\n", __FUNCTION__, __LINE__, p_VirtIf->Alias)); @@ -2998,13 +2987,23 @@ static eWanState_t wan_transition_ipv6_down(WanMgr_IfaceSM_Controller_t* pWanIfa else { /* Remove IPv6 default route and global addresses */ - if (WanMgr_RemoveIPv6RouteAndAddress(p_VirtIf->Name) != RETURN_OK) + if (WanMgr_RemoveIPv6RouteAndAddress(p_VirtIf->Name, p_VirtIf->IP.Ipv6Data.address) != RETURN_OK) { CcspTraceError(("%s %d - Failed to remove IPv6 route and address for '%s'\n", __FUNCTION__, __LINE__, p_VirtIf->Name)); } } + WanManager_UpdateInterfaceStatus (p_VirtIf, WANMGR_IFACE_CONNECTION_IPV6_DOWN); + //clear IPv6 lease from the interface data + memset(&(p_VirtIf->IP.Ipv6Data), 0, sizeof(WANMGR_IPV6_DATA)); + if (p_VirtIf->IP.pIpcIpv6Data != NULL ) + { + //free memory + free(p_VirtIf->IP.pIpcIpv6Data); + p_VirtIf->IP.pIpcIpv6Data = NULL; + } + #if defined(FEATURE_464XLAT) xlat_status = xlat_state_get(); if(xlat_status == XLAT_ON) @@ -3885,7 +3884,7 @@ static eWanState_t wan_state_obtaining_ip_addresses(WanMgr_IfaceSM_Controller_t* p_VirtIf->IP.Ipv6Changed = FALSE; return WAN_STATE_OBTAINING_IP_ADDRESSES; } - if (checkIpv6LanAddressIsReadyToUse(p_VirtIf) == RETURN_OK) + if (checkIpv6AddressIsReadyToUse(p_VirtIf) == RETURN_OK) { return wan_transition_ipv6_up(pWanIfaceCtrl); } @@ -3956,7 +3955,7 @@ static eWanState_t wan_state_standby(WanMgr_IfaceSM_Controller_t* pWanIfaceCtrl) } p_VirtIf->IP.Ipv6Changed = FALSE; } - if (checkIpv6LanAddressIsReadyToUse(p_VirtIf) == RETURN_OK) + if (checkIpv6AddressIsReadyToUse(p_VirtIf) == RETURN_OK) { ret = wan_transition_ipv6_up(pWanIfaceCtrl); CcspTraceInfo((" %s %d - IPv6 Address Assigned to Bridge Yet.\n", __FUNCTION__, __LINE__)); @@ -4059,7 +4058,7 @@ static eWanState_t wan_state_ipv4_leased(WanMgr_IfaceSM_Controller_t* pWanIfaceC p_VirtIf->IP.Ipv6Changed = FALSE; return WAN_STATE_IPV4_LEASED; } - if (checkIpv6LanAddressIsReadyToUse(p_VirtIf) == RETURN_OK) + if (checkIpv6AddressIsReadyToUse(p_VirtIf) == RETURN_OK) { return wan_transition_ipv6_up(pWanIfaceCtrl); } @@ -4167,7 +4166,7 @@ static eWanState_t wan_state_ipv6_leased(WanMgr_IfaceSM_Controller_t* pWanIfaceC } #if defined(FEATURE_MAPT) || defined(FEATURE_SUPPORT_MAPT_NAT46) || defined(FEATURE_MAPE) else if (pInterface->Selection.Status == WAN_IFACE_ACTIVE && - ((p_VirtIf->EnableMAPT == TRUE && p_VirtIf->MAP.MaptStatus == WAN_IFACE_MAPT_STATE_UP && checkIpv6LanAddressIsReadyToUse(p_VirtIf) ==RETURN_OK) + ((p_VirtIf->EnableMAPT == TRUE && p_VirtIf->MAP.MaptStatus == WAN_IFACE_MAPT_STATE_UP && checkIpv6AddressIsReadyToUse(p_VirtIf) ==RETURN_OK) || (p_VirtIf->MAP.dhcp6cMAPparameters.mapType == MAP_TYPE_MAPE && p_VirtIf->Status == WAN_IFACE_STATUS_UP && p_VirtIf->MAP.MapeStatus == WAN_IFACE_MAPE_STATE_UP))) { CcspTraceInfo(("%s %d - calling wan_transition_map_up \n", __FUNCTION__, __LINE__)); @@ -4196,18 +4195,6 @@ static eWanState_t wan_state_ipv6_leased(WanMgr_IfaceSM_Controller_t* pWanIfaceC WanMgr_CheckDefaultRA(p_VirtIf); -#if defined(FEATURE_IPOE_HEALTH_CHECK) && defined(IPOE_HEALTH_CHECK_LAN_SYNC_SUPPORT) - if(lanState == LAN_STATE_STOPPED) - { - WanMgr_SendMsgTo_ConnectivityCheck(pWanIfaceCtrl, CONNECTION_MSG_IPV6 , FALSE); - lanState = LAN_STATE_RESET; - } - else if(lanState == LAN_STATE_STARTED) - { - WanMgr_SendMsgTo_ConnectivityCheck(pWanIfaceCtrl, CONNECTION_MSG_IPV6 , TRUE); - lanState = LAN_STATE_RESET; - } -#endif return WAN_STATE_IPV6_LEASED; } @@ -4306,7 +4293,7 @@ static eWanState_t wan_state_dual_stack_active(WanMgr_IfaceSM_Controller_t* pWan } #if defined(FEATURE_MAPT) || defined(FEATURE_SUPPORT_MAPT_NAT46) || defined(FEATURE_MAPE) else if (pInterface->Selection.Status == WAN_IFACE_ACTIVE && - ((p_VirtIf->EnableMAPT == TRUE && p_VirtIf->MAP.MaptStatus == WAN_IFACE_MAPT_STATE_UP && checkIpv6LanAddressIsReadyToUse(p_VirtIf) ==RETURN_OK) + ((p_VirtIf->EnableMAPT == TRUE && p_VirtIf->MAP.MaptStatus == WAN_IFACE_MAPT_STATE_UP && checkIpv6AddressIsReadyToUse(p_VirtIf) ==RETURN_OK) || (p_VirtIf->MAP.dhcp6cMAPparameters.mapType == MAP_TYPE_MAPE && p_VirtIf->Status == WAN_IFACE_STATUS_UP && p_VirtIf->MAP.MapeStatus == WAN_IFACE_MAPE_STATE_UP))) { CcspTraceInfo(("%s %d - calling wan_transition_map_up \n", __FUNCTION__, __LINE__)); @@ -4342,18 +4329,6 @@ static eWanState_t wan_state_dual_stack_active(WanMgr_IfaceSM_Controller_t* pWan WanMgr_MonitorDhcpApps(pWanIfaceCtrl); WanMgr_CheckDefaultRA(p_VirtIf); -#if defined(FEATURE_IPOE_HEALTH_CHECK) && defined(IPOE_HEALTH_CHECK_LAN_SYNC_SUPPORT) - if(lanState == LAN_STATE_STOPPED) - { - WanMgr_SendMsgTo_ConnectivityCheck(pWanIfaceCtrl, CONNECTION_MSG_IPV6 , FALSE); - lanState = LAN_STATE_RESET; - } - else if(lanState == LAN_STATE_STARTED) - { - WanMgr_SendMsgTo_ConnectivityCheck(pWanIfaceCtrl, CONNECTION_MSG_IPV6 , TRUE); - lanState = LAN_STATE_RESET; - } -#endif return WAN_STATE_DUAL_STACK_ACTIVE; } @@ -4498,18 +4473,7 @@ static eWanState_t wan_state_map_active(WanMgr_IfaceSM_Controller_t* pWanIfaceCt WanMgr_MonitorDhcpApps(pWanIfaceCtrl); WanMgr_CheckDefaultRA(p_VirtIf); -#if defined(FEATURE_IPOE_HEALTH_CHECK) && defined(IPOE_HEALTH_CHECK_LAN_SYNC_SUPPORT) - if(lanState == LAN_STATE_STOPPED) - { - WanMgr_SendMsgTo_ConnectivityCheck(pWanIfaceCtrl, CONNECTION_MSG_IPV6 , FALSE); - lanState = LAN_STATE_RESET; - } - else if(lanState == LAN_STATE_STARTED) - { - WanMgr_SendMsgTo_ConnectivityCheck(pWanIfaceCtrl, CONNECTION_MSG_IPV6 , TRUE); - lanState = LAN_STATE_RESET; - } -#endif + return WAN_STATE_MAP_ACTIVE; } diff --git a/source/WanManager/wanmgr_ipc.c b/source/WanManager/wanmgr_ipc.c index 5d4e59b2..27d96cac 100644 --- a/source/WanManager/wanmgr_ipc.c +++ b/source/WanManager/wanmgr_ipc.c @@ -449,7 +449,7 @@ static void WanMgr_RemoveSingleQuote(char *buf) return 0; } -ANSC_STATUS WanMgr_SendMsgToIHC (ipoe_msg_type_t msgType, char *ifName) +ANSC_STATUS WanMgr_SendMsgToIHC (ipoe_msg_type_t msgType, DML_VIRTUAL_IFACE *p_VirtIf ) { int sock = -1; int conn = -1; @@ -462,25 +462,7 @@ ANSC_STATUS WanMgr_SendMsgToIHC (ipoe_msg_type_t msgType, char *ifName) if (msgType == IPOE_MSG_WAN_CONNECTION_IPV6_UP) { // V6 UP Message needs Wan V6 IP - char* pattern = NULL; - char ipv6_prefix[INET6_ADDRSTRLEN] = {0}; - - sysevent_get(sysevent_fd, sysevent_token, SYSCFG_FIELD_IPV6_PREFIX, ipv6_prefix, sizeof(ipv6_prefix)); - if(ipv6_prefix == NULL || *ipv6_prefix == '\0'|| (0 == strncmp(ipv6_prefix, "(null)", strlen("(null)")))) - { - CcspTraceError(("[%s-%d] Unable to get ipv6_prefix..\n", __FUNCTION__, __LINE__)); - return ANSC_STATUS_FAILURE; - } - - pattern = strstr(ipv6_prefix, "/"); - if (pattern == NULL) - { - CcspTraceError(("[%s-%d] Invalid ipv6_prefix :%s\n", __FUNCTION__, __LINE__, ipv6_prefix)); - return ANSC_STATUS_FAILURE; - } - sprintf(pattern, "%c%c", '1', '\0'); //Form the global address with ::1 - strncpy(msgBody.ipv6Address, ipv6_prefix, sizeof(ipv6_prefix)); - + strncpy(msgBody.ipv6Address, p_VirtIf->IP.Ipv6Data.address, sizeof(msgBody.ipv6Address) - 1); if( 0 == syscfg_get( NULL, "ntp_server1", domainName, sizeof(domainName)) ) { WanMgr_RemoveSingleQuote(domainName); @@ -495,16 +477,7 @@ ANSC_STATUS WanMgr_SendMsgToIHC (ipoe_msg_type_t msgType, char *ifName) } else if (msgType == IPOE_MSG_WAN_CONNECTION_UP) { - char ipv4_wan_address[IP_ADDR_LENGTH] = {0}; - char sysevent_param_name[BUFLEN_64] = {0}; - snprintf(sysevent_param_name, sizeof(sysevent_param_name), SYSEVENT_IPV4_IP_ADDRESS, ifName); - sysevent_get(sysevent_fd, sysevent_token, sysevent_param_name, ipv4_wan_address, sizeof(ipv4_wan_address)); - if(ipv4_wan_address == NULL || *ipv4_wan_address == '\0'|| (0 == strncmp(ipv4_wan_address, "(null)", strlen("(null)")))) - { - CcspTraceError(("[%s-%d] Unable to get ipv4_erouter0_ipaddr..\n", __FUNCTION__, __LINE__)); - return ANSC_STATUS_FAILURE; - } - strncpy(msgBody.ipv4Address, ipv4_wan_address, sizeof(ipv4_wan_address)); + strncpy(msgBody.ipv4Address, p_VirtIf->IP.Ipv4Data.ip, sizeof(msgBody.ipv4Address)-1); if( 0 == syscfg_get( NULL, "ntp_server1", domainName, sizeof(domainName)) ) { @@ -518,9 +491,9 @@ ANSC_STATUS WanMgr_SendMsgToIHC (ipoe_msg_type_t msgType, char *ifName) CcspTraceInfo(("[%s-%d] Sending IPOE_MSG_WAN_CONNECTION_UP msg with addr :%s and domainName: [%s] \n", __FUNCTION__, __LINE__, msgBody.ipv4Address, msgBody.domainName)); } - strncpy(msgBody.ifName, ifName, IFNAME_LENGTH-1); + strncpy(msgBody.ifName, p_VirtIf->Name, IFNAME_LENGTH-1); - CcspTraceInfo(("[%s-%d] Sending msg = %d for interface %s \n", __FUNCTION__, __LINE__, msgType, ifName)); + CcspTraceInfo(("[%s-%d] Sending msg = %d for interface %s \n", __FUNCTION__, __LINE__, msgType, p_VirtIf->Name)); int bytes = 0; int msgSize = sizeof(ipc_ihc_data_t); diff --git a/source/WanManager/wanmgr_ipc.h b/source/WanManager/wanmgr_ipc.h index f0d6d8b2..d8a716b7 100644 --- a/source/WanManager/wanmgr_ipc.h +++ b/source/WanManager/wanmgr_ipc.h @@ -27,7 +27,7 @@ #include "wanmgr_interface_sm.h" #ifdef FEATURE_IPOE_HEALTH_CHECK -ANSC_STATUS WanMgr_SendMsgToIHC (ipoe_msg_type_t msgType, char *ifName); +ANSC_STATUS WanMgr_SendMsgToIHC (ipoe_msg_type_t msgType, DML_VIRTUAL_IFACE *p_VirtIf); #endif diff --git a/source/WanManager/wanmgr_net_utils.c b/source/WanManager/wanmgr_net_utils.c index 4ce7cb06..e4833936 100644 --- a/source/WanManager/wanmgr_net_utils.c +++ b/source/WanManager/wanmgr_net_utils.c @@ -326,114 +326,72 @@ int isModuleLoaded(char *moduleName) ****************************************************************************/ static INT IsIPObtained(char *pInterfaceName); -int WanManager_Ipv6PrefixUtil(char *ifname, Ipv6OperType opr, int preflft, int vallft) +/*************************************************************************** + * @brief Utility function used to perform operation on IPV6 addresses + * for a particular interface + * @param p_VirtIf Pointer to the virtual interface + * @param opr indicates operation type (Delete/Set) + * @return 0 upon success else -1 returned + ***************************************************************************/ +int WanManager_Ipv6AddrUtil(DML_VIRTUAL_IFACE* p_VirtIf,Ipv6OperType opr) { char cmdLine[128] = {0}; - char prefix[BUFLEN_48] = {0}; - char prefixAddr[BUFLEN_48] = {0}; - char IfaceName[BUFLEN_16] = {0}; - int BridgeMode = 0; - - memset(prefix, 0, sizeof(prefix)); - sysevent_get(sysevent_fd, sysevent_token, SYSEVENT_FIELD_IPV6_PREFIX, prefix, sizeof(prefix)); - - memset(prefixAddr, 0, sizeof(prefixAddr)); - sysevent_get(sysevent_fd, sysevent_token, SYSEVENT_GLOBAL_IPV6_PREFIX_SET, prefixAddr, sizeof(prefixAddr)); - - { //TODO : temporary debug code to identify the bridgemode sysevent failure issue. - char Output[BUFLEN_16] = {0}; - if (sysevent_get(sysevent_fd, sysevent_token, "bridge_mode", Output, sizeof(Output)) !=0) - { - CcspTraceError(("%s-%d: bridge_mode sysevent get failed. \n", __FUNCTION__, __LINE__)); - } - BridgeMode = atoi(Output); - CcspTraceInfo(("%s-%d: <> bridge_mode sysevent value set to =%d \n", __FUNCTION__, __LINE__, BridgeMode)); - } - - /*TODO: - *Below Code should be removed once V6 Prefix/IP is assigned on erouter0 Instead of brlan0 for sky Devices. - */ - strcpy(IfaceName, LAN_BRIDGE_NAME); - if (WanMgr_isBridgeModeEnabled() == TRUE) - { - memset(IfaceName, 0, sizeof(IfaceName)); - strncpy(IfaceName, ifname, strlen(ifname)); - } - - CcspTraceInfo(("%s-%d: IfaceName=%s \n", __FUNCTION__, __LINE__, IfaceName)); switch (opr) { case DEL_ADDR: { - if (strlen(prefix) > 0) + if (strlen( p_VirtIf->IP.Ipv6Data.address) > 0) { -#if !(defined (_XB6_PRODUCT_REQ_) || defined (_CBR2_PRODUCT_REQ_) || defined(_PLATFORM_RASPBERRYPI_)) || defined(_RDKB_GLOBAL_PRODUCT_REQ_) //Do not delete prefix from LAn bridge for the comcast platforms. -#if defined(_RDKB_GLOBAL_PRODUCT_REQ_) - WanMgr_Config_Data_t *pWanConfigData = WanMgr_GetConfigData_locked(); - unsigned char ConfigureWANIPv6OnLANBridgeSupport = FALSE; - - if( NULL != pWanConfigData ) - { - ConfigureWANIPv6OnLANBridgeSupport = pWanConfigData->data.ConfigureWANIPv6OnLANBridgeSupport; - WanMgrDml_GetConfigData_release(pWanConfigData); - } + memset(cmdLine, 0, sizeof(cmdLine)); + snprintf(cmdLine, sizeof(cmdLine), "ip -6 addr del %s/128 dev %s", p_VirtIf->IP.Ipv6Data.address, p_VirtIf->Name); + if (WanManager_DoSystemActionWithStatus("ip -6 addr del ADDR dev xxxx", cmdLine) != 0) + CcspTraceError(("failed to run cmd: %s", cmdLine)); - if ( TRUE == ConfigureWANIPv6OnLANBridgeSupport ) -#endif /** _RDKB_GLOBAL_PRODUCT_REQ_ */ - { - 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); -#else - snprintf(cmdLine, sizeof(cmdLine), "ip -6 route flush %s ", prefix); -#endif - if (WanManager_DoSystemActionWithStatus("ip -6 route flush PREFIX ", cmdLine) != 0) + snprintf(cmdLine, sizeof(cmdLine), "ip -6 route flush match %s ", p_VirtIf->IP.Ipv6Data.address); + + if (WanManager_DoSystemActionWithStatus(cmdLine, cmdLine) != 0) CcspTraceError(("failed to run cmd: %s", cmdLine)); - CcspTraceInfo(("%s-%d: Successfully del addr and route from Interface %s, prefix=%s, prefixAddr=%s \n", - __FUNCTION__, __LINE__, IfaceName, prefix, prefixAddr)); + CcspTraceInfo(("%s-%d: Successfully del addr and route from Interface %s, Ipv6 Addr=%s \n", + __FUNCTION__, __LINE__, p_VirtIf->Name, p_VirtIf->IP.Ipv6Data.address)); memset(cmdLine, 0, sizeof(cmdLine)); snprintf(cmdLine, sizeof(cmdLine), "ip -6 route delete default"); if (WanManager_DoSystemActionWithStatus("ip -6 route delete default", cmdLine) != 0) CcspTraceError(("failed to run cmd: %s", cmdLine)); + CcspTraceInfo(("%s-%d: Successfully deleted ipv6 default route\n", __FUNCTION__, __LINE__)); } else { - CcspTraceError(("%s-%d: Failed to delete addr and route from Interface %s, prefix=%s, prefixAddr=%s \n", - __FUNCTION__, __LINE__, IfaceName, prefix, prefixAddr)); + CcspTraceError(("%s-%d: Failed to delete addr and route from Interface %s, IPv6 Addr=%s \n", + __FUNCTION__, __LINE__, p_VirtIf->Name, p_VirtIf->IP.Ipv6Data.address)); } break; } + case SET_LFT: { - if (strlen(prefixAddr) > 0) + if (strlen(p_VirtIf->IP.Ipv6Data.address) > 0) { memset(cmdLine, 0, sizeof(cmdLine)); - snprintf(cmdLine, sizeof(cmdLine), "ip -6 addr change %s dev %s valid_lft %d preferred_lft %d ", prefixAddr, IfaceName, vallft, preflft); + snprintf(cmdLine, sizeof(cmdLine), "ip -6 addr change %s dev %s valid_lft %d preferred_lft %d ", p_VirtIf->IP.Ipv6Data.address, p_VirtIf->Name, p_VirtIf->IP.Ipv6Data.prefixVltime, p_VirtIf->IP.Ipv6Data.prefixPltime); if (WanManager_DoSystemActionWithStatus("processDhcp6cStateChanged: ip -6 addr change L3IfName", (cmdLine)) != 0) CcspTraceError(("failed to run cmd: %s", cmdLine)); - CcspTraceInfo(("%s-%d: Successfully updated addr from Interface %s, prefixAddr=%s, vallft=%d, preflft=%d \n", - __FUNCTION__, __LINE__, IfaceName, prefixAddr, vallft, preflft)); + CcspTraceInfo(("%s-%d: Successfully updated addr from Interface %s, Ipv6 Addr=%s, vallft=%d, preflft=%d \n", + __FUNCTION__, __LINE__, p_VirtIf->Name, p_VirtIf->IP.Ipv6Data.address, p_VirtIf->IP.Ipv6Data.prefixVltime, p_VirtIf->IP.Ipv6Data.prefixPltime)); } else { - CcspTraceError(("%s-%d: Failed to update addr from Interface %s, prefixAddr=%s, vallft=%d, preflft=%d \n", - __FUNCTION__, __LINE__, IfaceName, prefixAddr, vallft, preflft)); + CcspTraceError(("%s-%d: Failed to update addr from Interface %s, Ipv6 Addr=%s, vallft=%d, preflft=%d \n", + __FUNCTION__, __LINE__, p_VirtIf->Name, p_VirtIf->IP.Ipv6Data.address, p_VirtIf->IP.Ipv6Data.prefixVltime, p_VirtIf->IP.Ipv6Data.prefixPltime)); } break; } } - return 0; } diff --git a/source/WanManager/wanmgr_net_utils.h b/source/WanManager/wanmgr_net_utils.h index 69e42d12..ce0439c3 100644 --- a/source/WanManager/wanmgr_net_utils.h +++ b/source/WanManager/wanmgr_net_utils.h @@ -37,8 +37,6 @@ #define PTM_IFC_STR "ptm" #define PHY_WAN_IF_NAME "erouter0" #define ETH_BRIDGE_NAME "brlan0" -#define LAN_BRIDGE_NAME "brlan0" -// #define WAN_STATUS_UP "up" #define WAN_STATUS_DOWN "down" @@ -160,13 +158,11 @@ BOOL WanManager_IsApplicationRunning(const char *appName, const char * args); /*************************************************************************** * @brief Utility function used to perform operation on IPV6 addresses * for a particular interface - * @param ifname string indicates interface name + * @param p_VirtIf Pointer to the virtual interface * @param opr indicates operation type (Delete/Set) - * @param preflft indicates preferred lifetime - * @param vallft indicates valid lifetime * @return 0 upon success else -1 returned ***************************************************************************/ -int WanManager_Ipv6PrefixUtil(char *ifname,Ipv6OperType opr,int preflft,int vallft); +int WanManager_Ipv6AddrUtil(DML_VIRTUAL_IFACE* p_VirtIf,Ipv6OperType opr); /*************************************************************************** * @brief Utility function used to check a process is running using PID diff --git a/source/WanManager/wanmgr_sysevents.c b/source/WanManager/wanmgr_sysevents.c index 823b0285..8a45f6c0 100644 --- a/source/WanManager/wanmgr_sysevents.c +++ b/source/WanManager/wanmgr_sysevents.c @@ -67,6 +67,7 @@ extern int WanMgr_TriggerPrimaryDnsConnectivityRestart(void); #endif #endif + static int isDefaultGatewayAdded = 0; //global varibale for default route status. static int lan_wan_started = 0; static int ipv4_connection_up = 0; @@ -77,10 +78,6 @@ static int set_default_conf_entry(); int mapt_feature_enable_changed = FALSE; #endif -#if defined(FEATURE_IPOE_HEALTH_CHECK) && defined(IPOE_HEALTH_CHECK_LAN_SYNC_SUPPORT) -lanState_t lanState = LAN_STATE_RESET; -#endif - #if defined(_DT_WAN_Manager_Enable_) bool needDibblerRestart = TRUE; #endif @@ -620,9 +617,10 @@ static void *WanManagerSyseventHandler(void *args) async_id_t primary_v6ipaddress_asyncid; #endif #endif - sysevent_set_options(sysevent_msg_fd, sysevent_msg_token, SYSEVENT_IPV6_TOGGLE, TUPLE_FLAG_EVENT); sysevent_setnotification(sysevent_msg_fd, sysevent_msg_token, SYSEVENT_IPV6_TOGGLE, &default_route_change_event_asyncid); + + #if defined (_HUB4_PRODUCT_REQ_) || defined(_RDKB_GLOBAL_PRODUCT_REQ_) sysevent_set_options(sysevent_msg_fd, sysevent_msg_token, SYSEVENT_ULA_ADDRESS, TUPLE_FLAG_EVENT); sysevent_setnotification(sysevent_msg_fd, sysevent_msg_token, SYSEVENT_ULA_ADDRESS, &lan_ula_address_event_asyncid); @@ -1218,7 +1216,6 @@ int Force_IPv6_toggle (char* wanInterface) } isDefaultGatewayAdded = 1; //Reset isDefaultGatewayAdded flag; - return ret; } diff --git a/source/WanManager/wanmgr_sysevents.h b/source/WanManager/wanmgr_sysevents.h index 84a9f62d..cd8edc82 100644 --- a/source/WanManager/wanmgr_sysevents.h +++ b/source/WanManager/wanmgr_sysevents.h @@ -205,18 +205,6 @@ #define WANMNGR_INTERFACE_DEFAULT_MTU_SIZE (1500) -/* IPOE_HEALTH_CHECK_LAN_SYNC_SUPPORT - stops and starts IPOE HEALTH CHECK Service based on lan events(SYSEVENT_LAN_STATUS). - * SKY IPoE Health check depends on the global ipv6 address configured on brlan0 and during the lan stop event brlan0 interface - * is made down affecting the IPoE service. - * */ -#if defined(FEATURE_IPOE_HEALTH_CHECK) && defined(IPOE_HEALTH_CHECK_LAN_SYNC_SUPPORT) -typedef enum{ - LAN_STATE_RESET = 0, - LAN_STATE_STOPPED, - LAN_STATE_STARTED, -}lanState_t; -#endif - //Bridge Mode #if defined(WAN_MANAGER_UNIFICATION_ENABLED) #define SYSEVENT_BRIDGE_MODE "bridge_mode"