IPACM: change src mac to bridge0
In SW-exception, the src mac of the DL traffic
to wifi-client will use bridge0's mac when device
is in bridge mode however in IPA-HW path, the src
mac of the DL traffic will use netdev's mac instead.
This failed in layer2 security check with some
special applications. The fix is to make src mac
consistent in both SW-exception/IPA-HW cases.
Change-Id: I2f248e2f3c265acfbecdeedac58e7e8dac36fec9
diff --git a/ipacm/inc/IPACM_Config.h b/ipacm/inc/IPACM_Config.h
index 54a4423..665b844 100644
--- a/ipacm/inc/IPACM_Config.h
+++ b/ipacm/inc/IPACM_Config.h
@@ -126,6 +126,12 @@
/* Store SW-enable or not */
bool ipa_sw_rt_enable;
+ /* Store bridge mode or not */
+ bool ipa_bridge_enable;
+
+ /* Store bridge netdev mac */
+ uint8_t bridge_mac[IPA_MAC_ADDR_SIZE];
+
/* Store the flt rule count for each producer client*/
int flt_rule_count_v4[IPA_CLIENT_CONS - IPA_CLIENT_PROD];
int flt_rule_count_v6[IPA_CLIENT_CONS - IPA_CLIENT_PROD];
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index dcc55d0..b40d91d 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -194,6 +194,7 @@
IPA_HANDLE_WAN_DOWN_TETHER, /* 57 ipacm_event_iface_up_tehter */
IPA_HANDLE_WAN_UP_V6_TETHER, /* 58 ipacm_event_iface_up_tehter */
IPA_HANDLE_WAN_DOWN_V6_TETHER, /* 59 ipacm_event_iface_up_tehter */
+ IPA_BRIDGE_LINK_UP_EVENT, /* 60 ipacm_event_data_all */
IPACM_EVENT_MAX
} ipa_cm_event_id;
diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp
index f7d764a..c718603 100644
--- a/ipacm/src/IPACM_Config.cpp
+++ b/ipacm/src/IPACM_Config.cpp
@@ -64,6 +64,7 @@
ipa_nat_max_entries = 0;
ipa_nat_iface_entries = 0;
ipa_sw_rt_enable = false;
+ ipa_bridge_enable = false;
isMCC_Mode = false;
ipa_max_valid_rm_entry = 0;
@@ -88,6 +89,7 @@
memset(flt_rule_count_v4, 0, (IPA_CLIENT_CONS - IPA_CLIENT_PROD)*sizeof(int));
memset(flt_rule_count_v6, 0, (IPA_CLIENT_CONS - IPA_CLIENT_PROD)*sizeof(int));
+ memset(bridge_mac, 0, IPA_MAC_ADDR_SIZE*sizeof(uint8_t));
IPACMDBG_H(" create IPACM_Config constructor\n");
return;
diff --git a/ipacm/src/IPACM_IfaceManager.cpp b/ipacm/src/IPACM_IfaceManager.cpp
index 3024ce6..59884ab 100644
--- a/ipacm/src/IPACM_IfaceManager.cpp
+++ b/ipacm/src/IPACM_IfaceManager.cpp
@@ -58,8 +58,10 @@
IPACM_EvtDispatcher::registr(IPA_WLAN_AP_LINK_UP_EVENT, this); // register for wlan AP-iface
#ifndef FEATURE_IPA_ANDROID
IPACM_EvtDispatcher::registr(IPA_WLAN_STA_LINK_UP_EVENT, this); // register for wlan STA-iface
+ /* only MDM targets support device on bridge mode */
+ IPACM_EvtDispatcher::registr(IPA_BRIDGE_LINK_UP_EVENT, this); // register for IPA_BRIDGE_LINK_UP_EVENT event
#endif /* not defined(FEATURE_IPA_ANDROID)*/
- IPACM_EvtDispatcher::registr(IPA_USB_LINK_UP_EVENT, this); // register for wlan STA-iface
+ IPACM_EvtDispatcher::registr(IPA_USB_LINK_UP_EVENT, this); // register for USB-iface
IPACM_EvtDispatcher::registr(IPA_WAN_EMBMS_LINK_UP_EVENT, this); // register for wan eMBMS-iface
return;
}
@@ -69,6 +71,7 @@
int ipa_interface_index;
ipacm_event_data_fid *evt_data = (ipacm_event_data_fid *)param;
ipacm_event_data_mac *StaData = (ipacm_event_data_mac *)param;
+ ipacm_event_data_all *data_all = (ipacm_event_data_all *)param;
ipacm_ifacemgr_data ifmgr_data = {0};
switch(event)
@@ -77,6 +80,21 @@
IPACMDBG_H(" RESET IPACM_cfg \n");
IPACM_Iface::ipacmcfg->Init();
break;
+ case IPA_BRIDGE_LINK_UP_EVENT:
+ IPACMDBG_H(" Save the bridge0 mac info in IPACM_cfg \n");
+ ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index);
+ /* check if iface is bridge interface*/
+ if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0)
+ {
+ IPACM_Iface::ipacmcfg->ipa_bridge_enable = true;
+ memcpy(IPACM_Iface::ipacmcfg->bridge_mac,
+ data_all->mac_addr,
+ sizeof(IPACM_Iface::ipacmcfg->bridge_mac));
+ IPACMDBG_H("cached bridge0 MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ IPACM_Iface::ipacmcfg->bridge_mac[0], IPACM_Iface::ipacmcfg->bridge_mac[1], IPACM_Iface::ipacmcfg->bridge_mac[2],
+ IPACM_Iface::ipacmcfg->bridge_mac[3], IPACM_Iface::ipacmcfg->bridge_mac[4], IPACM_Iface::ipacmcfg->bridge_mac[5]);
+ }
+ break;
case IPA_LINK_UP_EVENT:
IPACMDBG_H("Recieved IPA_LINK_UP_EVENT event: link up %d: \n", evt_data->if_index);
ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index);
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index 40bbec5..eb7243b 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -1846,6 +1846,14 @@
mac_addr,
IPA_MAC_ADDR_SIZE);
}
+ /* replace src mac to bridge mac_addr if any */
+ if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
+ {
+ memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
+ IPACM_Iface::ipacmcfg->bridge_mac,
+ IPA_MAC_ADDR_SIZE);
+ IPACMDBG_H("device is in bridge mode \n");
+ }
pHeaderDescriptor->commit = true;
pHeaderDescriptor->num_hdrs = 1;
@@ -1938,6 +1946,15 @@
mac_addr,
IPA_MAC_ADDR_SIZE);
}
+ /* replace src mac to bridge mac_addr if any */
+ if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
+ {
+ memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
+ IPACM_Iface::ipacmcfg->bridge_mac,
+ IPA_MAC_ADDR_SIZE);
+ IPACMDBG_H("device is in bridge mode \n");
+ }
+
pHeaderDescriptor->commit = true;
pHeaderDescriptor->num_hdrs = 1;
@@ -2360,7 +2377,14 @@
mac_addr,
IPA_MAC_ADDR_SIZE);
}
-
+ /* replace src mac to bridge mac_addr if any */
+ if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
+ {
+ memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
+ IPACM_Iface::ipacmcfg->bridge_mac,
+ IPA_MAC_ADDR_SIZE);
+ IPACMDBG_H("device is in bridge mode \n");
+ }
pHeaderDescriptor->commit = true;
pHeaderDescriptor->num_hdrs = 1;
@@ -2432,6 +2456,14 @@
mac_addr,
IPA_MAC_ADDR_SIZE);
}
+ /* replace src mac to bridge mac_addr if any */
+ if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
+ {
+ memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
+ IPACM_Iface::ipacmcfg->bridge_mac,
+ IPA_MAC_ADDR_SIZE);
+ IPACMDBG_H("device is in bridge mode \n");
+ }
pHeaderDescriptor->commit = true;
pHeaderDescriptor->num_hdrs = 1;
diff --git a/ipacm/src/IPACM_Netlink.cpp b/ipacm/src/IPACM_Netlink.cpp
index a343e24..30295b1 100644
--- a/ipacm/src/IPACM_Netlink.cpp
+++ b/ipacm/src/IPACM_Netlink.cpp
@@ -1376,13 +1376,13 @@
IPACMDBG("\n GOT RTM_NEWNEIGH event (%s) ip %d\n",dev_name,msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family);
}
- /* insert to command queue */
+ /* insert to command queue */
data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
if(data_all == NULL)
- {
+ {
IPACMERR("unable to allocate memory for event data_all\n");
return IPACM_FAILURE;
- }
+ }
memset(data_all, 0, sizeof(ipacm_event_data_all));
if(msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET6)
@@ -1390,11 +1390,11 @@
IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr);
IPACM_EVENT_COPY_ADDR_v6( data_all->ipv6_addr, msg_ptr->nl_neigh_info.attr_info.local_addr);
- data_all->ipv6_addr[0]=ntohl(data_all->ipv6_addr[0]);
- data_all->ipv6_addr[1]=ntohl(data_all->ipv6_addr[1]);
- data_all->ipv6_addr[2]=ntohl(data_all->ipv6_addr[2]);
- data_all->ipv6_addr[3]=ntohl(data_all->ipv6_addr[3]);
- data_all->iptype = IPA_IP_v6;
+ data_all->ipv6_addr[0]=ntohl(data_all->ipv6_addr[0]);
+ data_all->ipv6_addr[1]=ntohl(data_all->ipv6_addr[1]);
+ data_all->ipv6_addr[2]=ntohl(data_all->ipv6_addr[2]);
+ data_all->ipv6_addr[3]=ntohl(data_all->ipv6_addr[3]);
+ data_all->iptype = IPA_IP_v6;
}
else if (msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET)
{
@@ -1420,13 +1420,26 @@
memcpy(data_all->mac_addr,
msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr.sa_data,
sizeof(data_all->mac_addr));
- evt_data.event = IPA_NEW_NEIGH_EVENT;
- data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex;
-
- IPACMDBG_H("posting IPA_NEW_NEIGH_EVENT (%s):index:%d ip-family: %d\n",
+ data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex;
+ /* Add support to replace src-mac as bridge0 mac */
+ if((msg_ptr->nl_neigh_info.metainfo.ndm_family == AF_BRIDGE) &&
+ (msg_ptr->nl_neigh_info.metainfo.ndm_state == NUD_PERMANENT))
+ {
+ /* Posting IPA_BRIDGE_LINK_UP_EVENT event */
+ evt_data.event = IPA_BRIDGE_LINK_UP_EVENT;
+ IPACMDBG_H("posting IPA_BRIDGE_LINK_UP_EVENT (%s):index:%d \n",
+ dev_name,
+ data_all->if_index);
+ }
+ else
+ {
+ /* Posting new_neigh events for all LAN/WAN clients */
+ evt_data.event = IPA_NEW_NEIGH_EVENT;
+ IPACMDBG_H("posting IPA_NEW_NEIGH_EVENT (%s):index:%d ip-family: %d\n",
dev_name,
data_all->if_index,
msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family);
+ }
evt_data.evt_data = data_all;
IPACM_EvtDispatcher::PostEvt(&evt_data);
/* finish command queue */
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index 1971e90..97a6192 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -1782,6 +1782,15 @@
memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset],
get_client_memptr(wlan_client, num_wifi_client)->mac,
IPA_MAC_ADDR_SIZE);
+ /* replace src mac to bridge mac_addr if any */
+ if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
+ {
+ memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset+IPA_MAC_ADDR_SIZE],
+ IPACM_Iface::ipacmcfg->bridge_mac,
+ IPA_MAC_ADDR_SIZE);
+ IPACMDBG_H("device is in bridge mode \n");
+ }
+
}
else if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_STA_ID)
{
@@ -1888,6 +1897,15 @@
memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset],
get_client_memptr(wlan_client, num_wifi_client)->mac,
IPA_MAC_ADDR_SIZE);
+
+ /* replace src mac to bridge mac_addr if any */
+ if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
+ {
+ memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset+IPA_MAC_ADDR_SIZE],
+ IPACM_Iface::ipacmcfg->bridge_mac,
+ IPA_MAC_ADDR_SIZE);
+ IPACMDBG_H("device is in bridge mode \n");
+ }
}
else if (data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_STA_ID)
{