Merge "IPACM: Fix conntrack event comes earlier than new neighbor"
diff --git a/ipacm/inc/IPACM_Neighbor.h b/ipacm/inc/IPACM_Neighbor.h
index d37ae5b..55ab92e 100644
--- a/ipacm/inc/IPACM_Neighbor.h
+++ b/ipacm/inc/IPACM_Neighbor.h
@@ -54,6 +54,8 @@
 {
 	uint8_t mac_addr[6];
 	int iface_index;
+	uint32_t v4_addr;
+	int ipa_if_num;
 };
 
 class IPACM_Neighbor : public IPACM_Listener
diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp
index e096eed..8871303 100644
--- a/ipacm/src/IPACM_Main.cpp
+++ b/ipacm/src/IPACM_Main.cpp
@@ -188,26 +188,33 @@
 	while (1)
 	{
 		length = read(inotify_fd, buffer, INOTIFY_BUF_LEN);
-		struct inotify_event event;
-		memcpy(&event, buffer,sizeof(struct inotify_event));
-
 		if (length < 0)
 		{
-			IPACMERR("inotify read() error return length: %d and mask: 0x%x 0x%x\n", length, event.mask, mask);
+			IPACMERR("inotify read() error return length: %d and mask: 0x%x\n", length, mask);
 			return NULL;
 		}
 
-		if (event.len > 0)
+		struct inotify_event* event;
+		event = (struct inotify_event*)malloc(length);
+		if(event == NULL)
 		{
-			if ( (event.mask & IN_MODIFY) || (event.mask & IN_MOVE))
+			IPACMERR("Failed to allocate memory.\n");
+			return;
+		}
+		memset(event, 0, length);
+		memcpy(event, buffer, length);
+
+		if (event->len > 0)
+		{
+			if ( (event->mask & IN_MODIFY) || (event->mask & IN_MOVE))
 			{
-				if (event.mask & IN_ISDIR)
+				if (event->mask & IN_ISDIR)
 				{
-					IPACMDBG("The directory %s was 0x%x\n", event.name, event.mask);
+					IPACMDBG("The directory %s was 0x%x\n", event->name, event->mask);
 				}
-				else if (!strncmp(event.name, IPACM_FIREWALL_FILE_NAME, event.len)) // firewall_rule change
+				else if (!strncmp(event->name, IPACM_FIREWALL_FILE_NAME, event->len)) // firewall_rule change
 				{
-					IPACMDBG("File \"%s\" was 0x%x\n", event.name, event.mask);
+					IPACMDBG("File \"%s\" was 0x%x\n", event->name, event->mask);
 					IPACMDBG("The interested file %s .\n", IPACM_FIREWALL_FILE_NAME);
 
 					evt_data.event = IPA_FIREWALL_CHANGE_EVENT;
@@ -216,9 +223,9 @@
 					/* Insert IPA_FIREWALL_CHANGE_EVENT to command queue */
 					IPACM_EvtDispatcher::PostEvt(&evt_data);
 				}
-				else if (!strncmp(event.name, IPACM_CFG_FILE_NAME, event.len)) // IPACM_configuration change
+				else if (!strncmp(event->name, IPACM_CFG_FILE_NAME, event->len)) // IPACM_configuration change
 				{
-					IPACMDBG("File \"%s\" was 0x%x\n", event.name, event.mask);
+					IPACMDBG("File \"%s\" was 0x%x\n", event->name, event->mask);
 					IPACMDBG("The interested file %s .\n", IPACM_CFG_FILE_NAME);
 
 					evt_data.event = IPA_CFG_CHANGE_EVENT;
@@ -228,8 +235,9 @@
 					IPACM_EvtDispatcher::PostEvt(&evt_data);
 				}
 			}
-			IPACMDBG("Received monitoring event %s.\n", event.name);
+			IPACMDBG("Received monitoring event %s.\n", event->name);
 		}
+		free(event);
 	}
 
 	(void)inotify_rm_watch(inotify_fd, wd);
diff --git a/ipacm/src/IPACM_Neighbor.cpp b/ipacm/src/IPACM_Neighbor.cpp
index 8d9bdaa..beea12b 100644
--- a/ipacm/src/IPACM_Neighbor.cpp
+++ b/ipacm/src/IPACM_Neighbor.cpp
@@ -1,4 +1,4 @@
-/* 
+/*
 Copyright (c) 2013, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -64,7 +64,7 @@
 	IPACMDBG("Recieved event %d\n", event);
 
 	ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index);
-	
+
 	if (data->iptype == IPA_IP_v4)
 	{
 		if (data->ipv4_addr != 0) /* not 0.0.0.0 */
@@ -79,12 +79,13 @@
 					if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0)
 					{
 						data->if_index = neighbor_client[i].iface_index;
+    						neighbor_client[i].v4_addr = data->ipv4_addr; // cache client's previous ipv4 address
 						/* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */
-						if (event == IPA_NEW_NEIGH_EVENT) 
+						if (event == IPA_NEW_NEIGH_EVENT)
 						    evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
-						else 
+						else
 						    evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
-						
+
 	                                        data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
 				                if (data_all == NULL)
 				                {
@@ -94,7 +95,7 @@
 	                                        memcpy(data_all, data, sizeof(ipacm_event_data_all));
 						evt_data.evt_data = (void *)data_all;
 						IPACM_EvtDispatcher::PostEvt(&evt_data);
-						
+
 						/* ask for replaced iface name*/
 						ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index);
 						IPACMDBG("Posted event %d, with %s for ipv4\n",
@@ -109,9 +110,9 @@
 			else
 			{
 				/* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */
-				if (event == IPA_NEW_NEIGH_EVENT) 
+				if (event == IPA_NEW_NEIGH_EVENT)
 					evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
-				else 
+				else
 					evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
 
 	                        data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
@@ -127,11 +128,11 @@
 								 evt_data.event,
 								 IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
 		    }
-		}	
+		}
 	}
 	else
 	{   //ipv6 starts
-	
+
 		if ((data->ipv6_addr[0]) || (data->ipv6_addr[1]) || (data->ipv6_addr[2]) || (data->ipv6_addr[3]))
 		{
 		    IPACMDBG(" Got New_Neighbor event with ipv6 address \n");
@@ -147,7 +148,6 @@
 						/* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */
 						if (event == IPA_NEW_NEIGH_EVENT) evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
 						else evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
-						
 	                                        data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
 				                if (data_all == NULL)
 				                {
@@ -157,7 +157,6 @@
 	                                        memcpy(data_all, data, sizeof(ipacm_event_data_all));
 						evt_data.evt_data = (void *)data_all;
 						IPACM_EvtDispatcher::PostEvt(&evt_data);
-						
 						/* ask for replaced iface name*/
 						ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index);
 						IPACMDBG("Posted event %d, with %s for ipv6\n",
@@ -172,9 +171,9 @@
 			else
 			{
 				/* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */
-				if (event == IPA_NEW_NEIGH_EVENT) 
+				if (event == IPA_NEW_NEIGH_EVENT)
 					evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
-				else 
+				else
 					evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
 
 	                        data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
@@ -203,8 +202,45 @@
 					/* check if iface is not bridge interface*/
 					if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) != 0)
 					{
-                       neighbor_client[i].iface_index = data->if_index;
+
+						/* use previous ipv4 first */
+						if(data->if_index != neighbor_client[i].iface_index)
+						{
+							IPACMERR("update new kernel iface index \n");
+							neighbor_client[i].iface_index = data->if_index;
 						}
+
+						/* check if client associated with previous network interface */
+						if(ipa_interface_index != neighbor_client[i].ipa_if_num)
+						{
+							IPACMERR("client associate to different AP \n");
+							return;
+						}
+
+						if (neighbor_client[i].v4_addr != 0) /* not 0.0.0.0 */
+						{
+							evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
+							data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
+							if (data_all == NULL)
+							{
+								IPACMERR("Unable to allocate memory\n");
+								return;
+							}
+							data_all->iptype = IPA_IP_v4;
+							data_all->if_index = neighbor_client[i].iface_index;
+							data_all->ipv4_addr = neighbor_client[i].v4_addr; //use previous ipv4 address
+							memcpy(data_all->mac_addr,
+									neighbor_client[i].mac_addr,
+												sizeof(data_all->mac_addr));
+							evt_data.evt_data = (void *)data_all;
+							IPACM_EvtDispatcher::PostEvt(&evt_data);
+							/* ask for replaced iface name*/
+							ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index);
+							IPACMDBG("Posted event %d, with %s for ipv4 client re-connect\n",
+											evt_data.event,
+											IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
+						}
+					}
 					break;
 				}
 			}
@@ -214,13 +250,16 @@
 				/* check if iface is not bridge interface*/
 				if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) != 0)
 				{
-					  
+
 				if (num_neighbor_client_temp < IPA_MAX_NUM_NEIGHBOR_CLIENTS)
 				{
 					memcpy(neighbor_client[num_neighbor_client_temp].mac_addr,
 								 data->mac_addr,
 								 sizeof(data->mac_addr));
 					neighbor_client[num_neighbor_client_temp].iface_index = data->if_index;
+					/* cache the network interface client associated */
+					neighbor_client[num_neighbor_client_temp].ipa_if_num = ipa_interface_index;
+					neighbor_client[num_neighbor_client_temp].v4_addr = 0;
 					IPACMDBG("Copy wlan-iface client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n",
 									 neighbor_client[num_neighbor_client_temp].mac_addr[0],
 									 neighbor_client[num_neighbor_client_temp].mac_addr[1],
@@ -238,7 +277,7 @@
 					return;
 				}
 				}
-				
+
 			}
 		}
 	} //ipv6 ends
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index 8671fe7..3ec5fab 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -3443,14 +3443,7 @@
 		return;
 	}
 
-	if(iptype == IPA_IP_v4)
-	{
-		attrib->u.v4.src_addr = htonl(attrib->u.v4.src_addr);
-		attrib->u.v4.src_addr_mask = htonl(attrib->u.v4.src_addr_mask);
-		attrib->u.v4.dst_addr = htonl(attrib->u.v4.dst_addr);
-		attrib->u.v4.dst_addr_mask = htonl(attrib->u.v4.dst_addr_mask);
-	}
-	else if(iptype == IPA_IP_v6)
+	if(iptype == IPA_IP_v6)
 	{
 		int i;
 		for(i=0; i<4; i++)
@@ -3463,7 +3456,7 @@
 	}
 	else
 	{
-		IPACMERR("IP type is not expected: %d\n", iptype);
+		IPACMDBG("IP type is not IPv6, do nothing: %d\n", iptype);
 	}
 
 	return;