Merge "IPACM: Add support for Ethernet bridging in MCC Mode"
diff --git a/ipacm/inc/IPACM_Conntrack_NATApp.h b/ipacm/inc/IPACM_Conntrack_NATApp.h
index 7c97225..1fb12bf 100644
--- a/ipacm/inc/IPACM_Conntrack_NATApp.h
+++ b/ipacm/inc/IPACM_Conntrack_NATApp.h
@@ -52,6 +52,7 @@
uint32_t target_ip;
uint16_t target_port;
+ uint16_t public_ip;
uint16_t public_port;
u_int8_t protocol;
@@ -74,6 +75,7 @@
nat_table_entry *cache;
nat_table_entry temp[MAX_TEMP_ENTRIES];
uint32_t pub_ip_addr;
+ uint32_t pub_ip_addr_pre;
uint32_t nat_table_hdl;
int curCnt, max_entries;
@@ -118,6 +120,7 @@
void UpdateTcpUdpTo(uint32_t, int proto);
void AddTempEntry(const nat_table_entry *);
+ void CacheEntry(const nat_table_entry *);
void DeleteTempEntry(const nat_table_entry *);
void FlushTempEntries(uint32_t, bool);
};
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index 45ea6c0..72c348c 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -101,7 +101,7 @@
#define IPA_LAN_TO_LAN_WLAN_HDR_NAME_V4 "Lan2Lan_Wlan_v4"
#define IPA_LAN_TO_LAN_WLAN_HDR_NAME_V6 "Lan2Lan_Wlan_v6"
#define IPA_LAN_TO_LAN_MAX_WLAN_CLIENT 32
-#define IPA_LAN_TO_LAN_MAX_USB_CLIENT 1
+#define IPA_LAN_TO_LAN_MAX_USB_CLIENT 15
#define TCP_FIN_SHIFT 16
#define TCP_SYN_SHIFT 17
#define TCP_RST_SHIFT 18
@@ -179,6 +179,7 @@
IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT, /* 49 ipacm_event_data_fid */
IPA_WLAN_SWITCH_TO_SCC, /* 50 No Data */
IPA_WLAN_SWITCH_TO_MCC, /* 51 No Data */
+ IPA_CRADLE_WAN_MODE_SWITCH, /* 52 ipacm_event_cradle_wan_mode */
IPACM_EVENT_MAX
} ipa_cm_event_id;
@@ -200,6 +201,12 @@
UNKNOWN_IF
} ipacm_iface_type;
+typedef enum
+{
+ ROUTER = 0,
+ BRIDGE
+} ipacm_iface_mode;
+
typedef struct
{
struct nf_conntrack *ct;
@@ -210,6 +217,7 @@
{
char iface_name[IPA_IFACE_NAME_LEN];
ipacm_iface_type if_cat;
+ ipacm_iface_mode if_mode;
int netlink_interface_index;
} ipa_ifi_dev_name_t;
@@ -233,6 +241,11 @@
typedef struct
{
+ ipacm_iface_mode cradle_wan_mode;
+} ipacm_event_cradle_wan_mode;
+
+typedef struct
+{
enum ipa_ip_type iptype;
uint32_t ipv4_addr;
uint32_t ipv6_addr[4];
diff --git a/ipacm/inc/IPACM_Lan.h b/ipacm/inc/IPACM_Lan.h
index 505f426..bcfd898 100644
--- a/ipacm/inc/IPACM_Lan.h
+++ b/ipacm/inc/IPACM_Lan.h
@@ -185,6 +185,7 @@
int del_lan2lan_hdr(ipa_ip_type iptype, uint32_t hdr_hdl);
+ int handle_cradle_wan_mode_switch(bool is_wan_bridge_mode);
static ipa_hdr_l2_type usb_hdr_type;
diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h
index 07036f0..96bb0e6 100644
--- a/ipacm/inc/IPACM_Wan.h
+++ b/ipacm/inc/IPACM_Wan.h
@@ -116,6 +116,7 @@
static uint32_t backhaul_ipv6_prefix[2];
static bool embms_is_on;
+ static bool cradle_backhaul_is_wan_bridge;
private:
diff --git a/ipacm/inc/IPACM_Xml.h b/ipacm/inc/IPACM_Xml.h
index 90e0289..924e16d 100644
--- a/ipacm/inc/IPACM_Xml.h
+++ b/ipacm/inc/IPACM_Xml.h
@@ -84,6 +84,7 @@
#define IFACE_TAG "Iface"
#define NAME_TAG "Name"
#define CATEGORY_TAG "Category"
+#define MODE_TAG "Mode"
#define IPACMPRIVATESUBNETCFG_TAG "IPACMPrivateSubnet"
#define SUBNET_TAG "Subnet"
#define SUBNETADDRESS_TAG "SubnetAddress"
@@ -96,6 +97,8 @@
#define ODUIF_TAG "ODU"
#define EMBMSIF_TAG "EMBMS"
#define ETHIF_TAG "ETH"
+#define IFACE_ROUTER_MODE_TAG "ROUTER"
+#define IFACE_BRIDGE_MODE_TAG "BRIDGE"
#define IPACMALG_TAG "IPACMALG"
#define ALG_TAG "ALG"
#define Protocol_TAG "Protocol"
diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp
index 1a11012..5626367 100644
--- a/ipacm/src/IPACM_Config.cpp
+++ b/ipacm/src/IPACM_Config.cpp
@@ -145,7 +145,9 @@
{
strncpy(iface_table[i].iface_name, cfg->iface_config.iface_entries[i].iface_name, sizeof(iface_table[i].iface_name));
iface_table[i].if_cat = cfg->iface_config.iface_entries[i].if_cat;
- IPACMDBG_H("IPACM_Config::iface_table[%d] = %s, cat=%d\n", i, iface_table[i].iface_name, iface_table[i].if_cat);
+ iface_table[i].if_mode = cfg->iface_config.iface_entries[i].if_mode;
+ IPACMDBG_H("IPACM_Config::iface_table[%d] = %s, cat=%d, mode=%d\n", i, iface_table[i].iface_name,
+ iface_table[i].if_cat, iface_table[i].if_mode);
/* copy bridge interface name to ipacmcfg */
if( iface_table[i].if_cat == VIRTUAL_IF)
{
diff --git a/ipacm/src/IPACM_ConntrackClient.cpp b/ipacm/src/IPACM_ConntrackClient.cpp
index d8fe726..9de5911 100644
--- a/ipacm/src/IPACM_ConntrackClient.cpp
+++ b/ipacm/src/IPACM_ConntrackClient.cpp
@@ -113,19 +113,6 @@
goto IGNORE;
}
- if(!CtList->isWanUp())
- {
-#ifdef IPACM_DEBUG
- IPACMDBG("Wan is not up, ignoring below connections\n");
- char buf[1024];
- nfct_snprintf(buf, sizeof(buf), ct,
- type, NFCT_O_PLAIN, NFCT_OF_TIME);
- IPACMDBG("%s\n", buf);
- IPACMDBG("\n");
- ParseCTMessage(ct);
-#endif
- goto IGNORE;
- }
#endif
ct_data = (ipacm_ct_evt_data *)malloc(sizeof(ipacm_ct_evt_data));
diff --git a/ipacm/src/IPACM_ConntrackListener.cpp b/ipacm/src/IPACM_ConntrackListener.cpp
index e00f921..9e66a00 100644
--- a/ipacm/src/IPACM_ConntrackListener.cpp
+++ b/ipacm/src/IPACM_ConntrackListener.cpp
@@ -213,6 +213,7 @@
if(nat_iface_ipv4_addr[j] == 0)
{
nat_iface_ipv4_addr[j] = data->ipv4_addr;
+ nat_inst->ResetPwrSaveIf(data->ipv4_addr);
nat_inst->FlushTempEntries(data->ipv4_addr, true);
break;
}
@@ -702,11 +703,13 @@
{
IPACMDBG("orig src ip:0x%x equal to wan ip\n",orig_src_ip);
status = IPS_SRC_NAT;
+ rule.public_ip = wan_ipaddr;
}
else if(orig_dst_ip == wan_ipaddr)
{
IPACMDBG("orig Dst IP:0x%x equal to wan ip\n",orig_dst_ip);
status = IPS_DST_NAT;
+ rule.public_ip = wan_ipaddr;
}
else
{
@@ -933,7 +936,12 @@
if(TCP_CONNTRACK_ESTABLISHED == tcp_state)
{
IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED(%d)\n", tcp_state);
- if(isTempEntry)
+ if(!CtList->isWanUp())
+ {
+ IPACMDBG("Wan is not up, cache connections\n");
+ nat_inst->CacheEntry(&rule);
+ }
+ else if(isTempEntry)
{
nat_inst->AddTempEntry(&rule);
}
@@ -973,7 +981,12 @@
if(NFCT_T_NEW == type)
{
IPACMDBG("New UDP connection at time %ld\n", time(NULL));
- if(isTempEntry)
+ if(!CtList->isWanUp())
+ {
+ IPACMDBG("Wan is not up, cache connections\n");
+ nat_inst->CacheEntry(&rule);
+ }
+ else if(isTempEntry)
{
nat_inst->AddTempEntry(&rule);
}
diff --git a/ipacm/src/IPACM_Conntrack_NATApp.cpp b/ipacm/src/IPACM_Conntrack_NATApp.cpp
index c4a7e52..0915fda 100644
--- a/ipacm/src/IPACM_Conntrack_NATApp.cpp
+++ b/ipacm/src/IPACM_Conntrack_NATApp.cpp
@@ -129,8 +129,19 @@
int NatApp::AddTable(uint32_t pub_ip)
{
int ret;
+ int cnt = 0;
+ ipa_nat_ipv4_rule nat_rule;
IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__);
+ /* Not reset the cache wait it timeout by destroy event */
+#if 0
+ if (pub_ip != pub_ip_addr_pre)
+ {
+ IPACMDBG("Reset the cache because NAT-ipv4 different\n");
+ memset(cache, 0, sizeof(nat_table_entry) * max_entries);
+ curCnt = 0;
+ }
+#endif
ret = ipa_nat_add_ipv4_tbl(pub_ip, max_entries, &nat_table_hdl);
if(ret)
{
@@ -138,17 +149,56 @@
return ret;
}
+ /* Add back the cashed NAT-entry */
+ if (pub_ip == pub_ip_addr_pre)
+ {
+ IPACMDBG("Restore the cache to ipa NAT-table\n");
+ for(cnt = 0; cnt < max_entries; cnt++)
+ {
+ if(cache[cnt].private_ip !=0)
+ {
+ memset(&nat_rule, 0 , sizeof(nat_rule));
+ nat_rule.private_ip = cache[cnt].private_ip;
+ nat_rule.target_ip = cache[cnt].target_ip;
+ nat_rule.target_port = cache[cnt].target_port;
+ nat_rule.private_port = cache[cnt].private_port;
+ nat_rule.public_port = cache[cnt].public_port;
+ nat_rule.protocol = cache[cnt].protocol;
+
+ if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0)
+ {
+ IPACMERR("unable to add the rule delete from cache\n");
+ memset(&cache[cnt], 0, sizeof(cache[cnt]));
+ curCnt--;
+ continue;
+ }
+ cache[cnt].enabled = true;
+
+ IPACMDBG("On wan-iface reset added below rule successfully\n");
+ iptodot("Private IP", nat_rule.private_ip);
+ iptodot("Target IP", nat_rule.target_ip);
+ IPACMDBG("Private Port:%d \t Target Port: %d\t", nat_rule.private_port, nat_rule.target_port);
+ IPACMDBG("Public Port:%d\n", nat_rule.public_port);
+ IPACMDBG("protocol: %d\n", nat_rule.protocol);
+ }
+ }
+ }
+
pub_ip_addr = pub_ip;
return 0;
}
void NatApp::Reset()
{
- memset(cache, 0, sizeof(nat_table_entry) * max_entries);
+ int cnt = 0;
nat_table_hdl = 0;
pub_ip_addr = 0;
- curCnt = 0;
+ /* NAT tbl deleted, reset enabled bit */
+ for(cnt = 0; cnt < max_entries; cnt++)
+ {
+ cache[cnt].enabled ==false;
+ }
}
int NatApp::DeleteTable(uint32_t pub_ip)
@@ -172,6 +222,7 @@
return ret;
}
+ pub_ip_addr_pre = pub_ip_addr;
Reset();
return 0;
}
@@ -208,9 +259,7 @@
int cnt = 0;
IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__);
- CHK_TBL_HDL();
-
- IPACMDBG("Received below nat entry for deletion\n");
+ IPACMDBG("Received below nat entry for deletion\n");
iptodot("Private IP", rule->private_ip);
iptodot("Target IP", rule->target_ip);
IPACMDBG("Private Port: %d\t Target Port: %d\t", rule->private_port, rule->target_port);
@@ -229,8 +278,7 @@
{
if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0)
{
- IPACMERR("%s() %d\n", __FUNCTION__, __LINE__);
- return -1;
+ IPACMERR("%s() %d deletion failed\n", __FUNCTION__, __LINE__);
}
IPACMDBG("Deleted Nat entry(%d) Successfully\n", cnt);
@@ -525,7 +573,6 @@
}
}
- CHK_TBL_HDL();
for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++)
{
@@ -579,6 +626,8 @@
for(cnt = 0; cnt < max_entries; cnt++)
{
+ IPACMDBG("cache (%d): enable %d, ip 0x%x\n", cnt, cache[cnt].enabled, cache[cnt].private_ip);
+
if(cache[cnt].private_ip == client_lan_ip &&
cache[cnt].enabled == false)
{
@@ -704,11 +753,14 @@
{
if(isAdd)
{
- ret = AddEntry(&temp[cnt]);
- if(ret)
+ if(temp[cnt].public_ip == pub_ip_addr)
{
- IPACMERR("unable to add temp entry: %d\n", ret);
- continue;
+ ret = AddEntry(&temp[cnt]);
+ if(ret)
+ {
+ IPACMERR("unable to add temp entry: %d\n", ret);
+ continue;
+ }
}
}
memset(&temp[cnt], 0, sizeof(nat_table_entry));
@@ -729,7 +781,6 @@
return -1;
}
- CHK_TBL_HDL();
for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++)
{
@@ -741,27 +792,28 @@
}
}
- for(cnt = 0; cnt < max_entries; cnt++)
+ for(cnt = 0; cnt < max_entries; cnt++)
+ {
+ if(cache[cnt].private_ip == ip_addr)
{
- if(cache[cnt].private_ip == ip_addr)
- {
-
- if(cache[cnt].enabled == true)
- {
+ if(cache[cnt].enabled == true)
+ {
if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0)
{
IPACMERR("unable to delete the rule\n");
continue;
}
- }
-
- memset(&cache[cnt], 0, sizeof(cache[cnt]));
- curCnt--;
- }
+ else
+ {
+ IPACMDBG("won't delete the rule\n");
+ cache[cnt].enabled = false;
+ }
+ }
+ IPACMDBG("won't delete the rule for entry %d, enabled %d\n",cnt, cache[cnt].enabled);
}
-
+ }
IPACMDBG("Deleted %d entries\n", (tmp - curCnt));
- return 0;
+ return 0;
}
int NatApp::DelEntriesOnSTAClntDiscon(uint32_t ip_addr)
@@ -775,7 +827,6 @@
return -1;
}
- CHK_TBL_HDL();
for(cnt = 0; cnt < max_entries; cnt++)
{
@@ -798,3 +849,61 @@
IPACMDBG("Deleted %d entries\n", (tmp - curCnt));
return 0;
}
+
+void NatApp::CacheEntry(const nat_table_entry *rule)
+{
+ int cnt;
+ if(rule->private_ip == 0 ||
+ rule->target_ip == 0 ||
+ rule->private_port == 0 ||
+ rule->target_port == 0 ||
+ rule->protocol == 0)
+ {
+ IPACMERR("Invalid Connection, ignoring it\n");
+ return;
+ }
+
+ if(!ChkForDup(rule))
+ {
+ for(; cnt < max_entries; cnt++)
+ {
+ if(cache[cnt].private_ip == 0 &&
+ cache[cnt].target_ip == 0 &&
+ cache[cnt].private_port == 0 &&
+ cache[cnt].target_port == 0 &&
+ cache[cnt].protocol == 0)
+ {
+ break;
+ }
+ }
+
+ if(max_entries == cnt)
+ {
+ IPACMERR("Error: Unable to add, reached maximum rules\n");
+ return;
+ }
+ else
+ {
+ cache[cnt].enabled = false;
+ cache[cnt].rule_hdl = 0;
+ cache[cnt].private_ip = rule->private_ip;
+ cache[cnt].target_ip = rule->target_ip;
+ cache[cnt].target_port = rule->target_port;
+ cache[cnt].private_port = rule->private_port;
+ cache[cnt].protocol = rule->protocol;
+ cache[cnt].timestamp = 0;
+ cache[cnt].public_port = rule->public_port;
+ cache[cnt].dst_nat = rule->dst_nat;
+ curCnt++;
+ }
+
+ }
+ else
+ {
+ IPACMERR("Duplicate rule. Ignore it\n");
+ return;
+ }
+
+ IPACMDBG("Cached rule(%d) successfully\n", cnt);
+ return;
+}
diff --git a/ipacm/src/IPACM_IfaceManager.cpp b/ipacm/src/IPACM_IfaceManager.cpp
index 573d7c6..80f7210 100644
--- a/ipacm/src/IPACM_IfaceManager.cpp
+++ b/ipacm/src/IPACM_IfaceManager.cpp
@@ -225,6 +225,7 @@
IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT, lan);
IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT, lan);
#endif
+ IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, lan);
IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, lan);
IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, lan);
IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", lan->dev_name, lan->ipa_if_num);
@@ -246,6 +247,7 @@
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, ETH);
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, ETH);
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, ETH);
+ IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, ETH);
IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, ETH);
IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, ETH);
IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", ETH->dev_name, ETH->ipa_if_num);
@@ -269,6 +271,7 @@
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, odu);
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, odu);
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, odu);
+ IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, odu);
IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, odu);
IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, odu);
IPACMDBG("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", odu->dev_name, odu->ipa_if_num);
@@ -319,6 +322,7 @@
IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT, wl);
IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT, wl);
#endif
+ IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, wl);
IPACM_EvtDispatcher::registr(IPA_WLAN_LINK_DOWN_EVENT, wl);
IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, wl);
#ifndef FEATURE_IPA_ANDROID
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index a5b5eae..2b757a6 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -732,6 +732,27 @@
}
break;
+ case IPA_CRADLE_WAN_MODE_SWITCH:
+ {
+ IPACMDBG_H("Received IPA_CRADLE_WAN_MODE_SWITCH event.\n");
+ ipacm_event_cradle_wan_mode* wan_mode = (ipacm_event_cradle_wan_mode*)param;
+ if(wan_mode == NULL)
+ {
+ IPACMERR("Event data is empty.\n");
+ return;
+ }
+
+ if(wan_mode->cradle_wan_mode == BRIDGE)
+ {
+ handle_cradle_wan_mode_switch(true);
+ }
+ else
+ {
+ handle_cradle_wan_mode_switch(false);
+ }
+ }
+ break;
+
default:
break;
}
@@ -1148,7 +1169,14 @@
flt_rule_entry.at_rear = true;
flt_rule_entry.flt_rule_hdl = -1;
flt_rule_entry.status = -1;
- flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; //IPA_PASS_TO_ROUTING
+ if(IPACM_Wan::cradle_backhaul_is_wan_bridge == true)
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+ }
+ else
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; //IPA_PASS_TO_ROUTING
+ }
flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl;
memcpy(&flt_rule_entry.rule.attrib,
@@ -2372,12 +2400,6 @@
goto fail;
}
#endif
- if(m_filtering.DeleteFilteringHdls(ipv6_icmp_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE) == false)
- {
- IPACMERR("Error Deleting ICMPv6 Filtering Rule, aborting...\n");
- res = IPACM_FAILURE;
- goto fail;
- }
#ifndef FEATURE_ETH_BRIDGE_LE
#ifdef CT_OPT
if (m_filtering.DeleteFilteringHdls(tcp_ctl_flt_rule_hdl_v4, IPA_IP_v4, NUM_TCP_CTL_FLT_RULE) == false)
@@ -2427,6 +2449,13 @@
if (ip_type != IPA_IP_v4 && rx_prop != NULL)
{
+ if(m_filtering.DeleteFilteringHdls(ipv6_icmp_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE) == false)
+ {
+ IPACMERR("Error Deleting ICMPv6 Filtering Rule, aborting...\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl,
IPA_IP_v6,
(IPV6_DEFAULT_FILTERTING_RULES + IPV6_DEFAULT_LAN_FILTERTING_RULES)) == false)
@@ -5425,5 +5454,85 @@
return IPACM_SUCCESS;
}
+int IPACM_Lan::handle_cradle_wan_mode_switch(bool is_wan_bridge_mode)
+{
+ struct ipa_flt_rule_mdfy flt_rule_entry;
+ int len = 0;
+ ipa_ioc_mdfy_flt_rule *m_pFilteringTable;
+
+ IPACMDBG_H("Handle wan mode swtich: is wan bridge mode?%d\n", is_wan_bridge_mode);
+
+ if (rx_prop == NULL)
+ {
+ IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
+ return IPACM_SUCCESS;
+ }
+
+ len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (1 * sizeof(struct ipa_flt_rule_mdfy));
+ m_pFilteringTable = (struct ipa_ioc_mdfy_flt_rule *)calloc(1, len);
+ if (m_pFilteringTable == NULL)
+ {
+ PERROR("Error Locate ipa_ioc_mdfy_flt_rule memory...\n");
+ return IPACM_FAILURE;
+ }
+
+ m_pFilteringTable->commit = 1;
+ m_pFilteringTable->ip = IPA_IP_v4;
+ m_pFilteringTable->num_rules = (uint8_t)1;
+
+ IPACMDBG_H("Retrieving routing hanle for table: %s\n",
+ IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name);
+ if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4))
+ {
+ IPACMERR("m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4=0x%p) Failed.\n",
+ &IPACM_Iface::ipacmcfg->rt_tbl_wan_v4);
+ free(m_pFilteringTable);
+ return IPACM_FAILURE;
+ }
+ IPACMDBG_H("Routing handle for table: %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl);
+
+
+ memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_mdfy)); // Zero All Fields
+ flt_rule_entry.status = -1;
+ flt_rule_entry.rule_hdl = lan_wan_fl_rule_hdl[0];
+
+ flt_rule_entry.rule.retain_hdr = 0;
+ flt_rule_entry.rule.to_uc = 0;
+ flt_rule_entry.rule.eq_attrib_type = 0;
+ if(is_wan_bridge_mode)
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+ }
+ else
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT;
+ }
+ flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl;
+
+ memcpy(&flt_rule_entry.rule.attrib,
+ &rx_prop->rx[0].attrib,
+ sizeof(flt_rule_entry.rule.attrib));
+
+ flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
+ flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x0;
+ flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x0;
+
+ memcpy(&m_pFilteringTable->rules[0], &flt_rule_entry, sizeof(flt_rule_entry));
+ if (false == m_filtering.ModifyFilteringRule(m_pFilteringTable))
+ {
+ IPACMERR("Error Modifying RuleTable(0) to Filtering, aborting...\n");
+ free(m_pFilteringTable);
+ return IPACM_FAILURE;
+ }
+ else
+ {
+ IPACMDBG_H("flt rule hdl = %d, status = %d\n",
+ m_pFilteringTable->rules[0].rule_hdl,
+ m_pFilteringTable->rules[0].status);
+ }
+ free(m_pFilteringTable);
+ return IPACM_SUCCESS;
+}
+
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index 92b4a5e..ddb7915 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -66,6 +66,7 @@
int IPACM_Wan::num_ipv6_modem_pdn = 0;
bool IPACM_Wan::embms_is_on = false;
+bool IPACM_Wan::cradle_backhaul_is_wan_bridge = false;
uint32_t IPACM_Wan::backhaul_ipv6_prefix[2];
@@ -501,7 +502,66 @@
case IPA_CFG_CHANGE_EVENT:
{
- if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != ipa_if_cate) &&
+ if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ipa_if_cate) &&
+ (m_is_sta_mode ==ECM_WAN))
+ {
+ IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category did not change(wan_mode:%d)\n", m_is_sta_mode);
+ IPACMDBG_H("Now the cradle wan mode is %d.\n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode);
+ if(is_default_gateway == true)
+ {
+ if(cradle_backhaul_is_wan_bridge == false && IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == BRIDGE)
+ {
+ IPACMDBG_H("Cradle wan mode switch to bridge mode.\n");
+ cradle_backhaul_is_wan_bridge = true;
+ }
+ else if(cradle_backhaul_is_wan_bridge == true && IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
+ {
+ IPACMDBG_H("Cradle wan mode switch to router mode.\n");
+ cradle_backhaul_is_wan_bridge = false;
+ }
+ else
+ {
+ IPACMDBG_H("No cradle mode switch, return.\n");
+ return;
+ }
+ /* post wan mode change event to LAN/WLAN */
+ if(IPACM_Wan::wan_up == true)
+ {
+ IPACMDBG_H("This interface is default GW.\n");
+ ipacm_cmd_q_data evt_data;
+ memset(&evt_data, 0, sizeof(evt_data));
+
+ ipacm_event_cradle_wan_mode *data_wan_mode = NULL;
+ data_wan_mode = (ipacm_event_cradle_wan_mode *)malloc(sizeof(ipacm_event_cradle_wan_mode));
+ if(data_wan_mode == NULL)
+ {
+ IPACMERR("unable to allocate memory.\n");
+ return;
+ }
+ data_wan_mode->cradle_wan_mode = IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode;
+ evt_data.event = IPA_CRADLE_WAN_MODE_SWITCH;
+ evt_data.evt_data = data_wan_mode;
+ IPACMDBG_H("Posting IPA_CRADLE_WAN_MODE_SWITCH event.\n");
+ IPACM_EvtDispatcher::PostEvt(&evt_data);
+ }
+ /* update the firewall flt rule actions */
+ if(active_v4)
+ {
+ del_dft_firewall_rules(IPA_IP_v4);
+ config_dft_firewall_rules(IPA_IP_v4);
+ }
+ if(active_v6)
+ {
+ del_dft_firewall_rules(IPA_IP_v6);
+ config_dft_firewall_rules(IPA_IP_v6);
+ }
+ }
+ else
+ {
+ IPACMDBG_H("This interface is not default GW, ignore.\n");
+ }
+ }
+ else if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != ipa_if_cate) &&
(m_is_sta_mode ==ECM_WAN))
{
IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category changed(wan_mode:%d)\n", m_is_sta_mode);
@@ -1027,6 +1087,14 @@
if (m_is_sta_mode !=Q6_WAN)
{
IPACM_Wan::backhaul_is_sta_mode = true;
+ if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == BRIDGE)
+ {
+ IPACM_Wan::cradle_backhaul_is_wan_bridge = true;
+ }
+ else
+ {
+ IPACM_Wan::cradle_backhaul_is_wan_bridge = false;
+ }
if((iptype==IPA_IP_v4) && (header_set_v4 != true))
{
header_partial_default_wan_v4 = true;
@@ -1566,13 +1634,13 @@
}
}
- /* see if default routes are setup before constructing full header */
- if(header_partial_default_wan_v4 == true)
+ /* see if default routes are setup before constructing full header */
+ if(header_partial_default_wan_v4 == true)
{
handle_route_add_evt(IPA_IP_v4);
}
- if(header_partial_default_wan_v6 == true)
+ if(header_partial_default_wan_v6 == true)
{
handle_route_add_evt(IPA_IP_v6);
}
@@ -1697,25 +1765,39 @@
flt_rule_entry.status = -1;
/* firewall disable, all traffic are allowed */
- if(firewall_config.firewall_enable == true)
+ if(firewall_config.firewall_enable == true)
{
- flt_rule_entry.at_rear = true;
+ flt_rule_entry.at_rear = true;
- /* default action for v4 is go DST_NAT unless user set to exception*/
- if(firewall_config.rule_action_accept == true)
- {
- flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
- }
- else
- {
- flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
- }
- }
+ /* default action for v4 is go DST_NAT unless user set to exception*/
+ if(firewall_config.rule_action_accept == true)
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
+ }
+ else
+ {
+ if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
+ }
+ else
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+ }
+ }
+ }
else
{
- flt_rule_entry.at_rear = true;
- flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
- }
+ flt_rule_entry.at_rear = true;
+ if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
+ }
+ else
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+ }
+ }
flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
memcpy(&flt_rule_entry.rule.attrib,
@@ -1776,14 +1858,21 @@
flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
/* Accept v4 matched rules*/
- if(firewall_config.rule_action_accept == true)
- {
- flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
- }
- else
- {
- flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
- }
+ if(firewall_config.rule_action_accept == true)
+ {
+ if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
+ }
+ else
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+ }
+ }
+ else
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
+ }
memcpy(&flt_rule_entry.rule.attrib,
&firewall_config.extd_firewall_entries[i].attrib,
@@ -1877,7 +1966,7 @@
flt_rule_entry.status = -1;
/* firewall disable, all traffic are allowed */
- if(firewall_config.firewall_enable == true)
+ if(firewall_config.firewall_enable == true)
{
flt_rule_entry.at_rear = true;
@@ -1888,14 +1977,28 @@
}
else
{
- flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
- }
- }
+ if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
+ }
+ else
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+ }
+ }
+ }
else
{
flt_rule_entry.at_rear = true;
- flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
- }
+ if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
+ }
+ else
+ {
+ flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+ }
+ }
flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
memcpy(&flt_rule_entry.rule.attrib,
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index e0f9a82..fd957a4 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -763,6 +763,27 @@
}
break;
+ case IPA_CRADLE_WAN_MODE_SWITCH:
+ {
+ IPACMDBG_H("Received IPA_CRADLE_WAN_MODE_SWITCH event.\n");
+ ipacm_event_cradle_wan_mode* wan_mode = (ipacm_event_cradle_wan_mode*)param;
+ if(wan_mode == NULL)
+ {
+ IPACMERR("Event data is empty.\n");
+ return;
+ }
+
+ if(wan_mode->cradle_wan_mode == BRIDGE)
+ {
+ handle_cradle_wan_mode_switch(true);
+ }
+ else
+ {
+ handle_cradle_wan_mode_switch(false);
+ }
+ }
+ break;
+
default:
break;
}
@@ -2212,17 +2233,6 @@
}
IPACMDBG_H("Deleted guest ap v4 filter rules successfully.\n");
#endif
-
- /* delete icmp filter rules */
- if(wlan_ap_index == 0)
- {
- if(m_filtering.DeleteFilteringHdls(ipv6_icmp_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE) == false)
- {
- IPACMERR("Error Deleting ICMPv6 Filtering Rule, aborting...\n");
- res = IPACM_FAILURE;
- goto fail;
- }
- }
#ifndef FEATURE_ETH_BRIDGE_LE
#ifdef CT_OPT
IPACMDBG_H("Delete tcp control flt rules.\n");
@@ -2281,6 +2291,16 @@
/* Delete v6 filtering rules */
if (ip_type != IPA_IP_v4 && rx_prop != NULL)
{
+ /* delete icmp filter rules */
+ if(wlan_ap_index == 0)
+ {
+ if(m_filtering.DeleteFilteringHdls(ipv6_icmp_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE) == false)
+ {
+ IPACMERR("Error Deleting ICMPv6 Filtering Rule, aborting...\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ }
IPACMDBG_H("Delete default %d v6 filter rules\n", IPV6_DEFAULT_FILTERTING_RULES);
/* delete default filter rules */
#ifdef FEATURE_ETH_BRIDGE_LE
diff --git a/ipacm/src/IPACM_Xml.cpp b/ipacm/src/IPACM_Xml.cpp
index 6ef4cc0..09fd2e3 100644
--- a/ipacm/src/IPACM_Xml.cpp
+++ b/ipacm/src/IPACM_Xml.cpp
@@ -292,6 +292,26 @@
}
}
}
+ else if (IPACM_util_icmp_string((char*)xml_node->name, MODE_TAG) == 0)
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ if (0 == strncasecmp(content_buf, IFACE_ROUTER_MODE_TAG, str_size))
+ {
+ config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_mode = ROUTER;
+ IPACMDBG_H("Iface mode %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_mode);
+ }
+ else if (0 == strncasecmp(content_buf, IFACE_BRIDGE_MODE_TAG, str_size))
+ {
+ config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_mode = BRIDGE;
+ IPACMDBG_H("Iface mode %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_mode);
+ }
+ }
+ }
else if (IPACM_util_icmp_string((char*)xml_node->name,
SUBNETADDRESS_TAG) == 0)
{
diff --git a/ipacm/src/IPACM_cfg.xml b/ipacm/src/IPACM_cfg.xml
index 95a7796..8f7e886 100644
--- a/ipacm/src/IPACM_cfg.xml
+++ b/ipacm/src/IPACM_cfg.xml
@@ -12,6 +12,7 @@
<Iface>
<Name>ecm0</Name>
<Category>LAN</Category>
+ <Mode>ROUTER</Mode>
</Iface>
<Iface>
<Name>rmnet_data0</Name>
@@ -144,4 +145,4 @@
<MaxNatEntries>500</MaxNatEntries>
</IPACMNAT>
</IPACM>
-</system>
\ No newline at end of file
+</system>