1 /*
2 Copyright (c) 2013, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7 		* Redistributions of source code must retain the above copyright
8 			notice, this list of conditions and the following disclaimer.
9 		* Redistributions in binary form must reproduce the above
10 			copyright notice, this list of conditions and the following
11 			disclaimer in the documentation and/or other materials provided
12 			with the distribution.
13 		* Neither the name of The Linux Foundation nor the names of its
14 			contributors may be used to endorse or promote products derived
15 			from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 /*!
30 	@file
31 	IPACM_Neighbor.cpp
32 
33 	@brief
34 	This file implements the functionality of handling IPACM Neighbor events.
35 
36 	@Author
37 	Skylar Chang
38 
39 */
40 
41 #include <sys/ioctl.h>
42 #include <IPACM_Neighbor.h>
43 #include <IPACM_EvtDispatcher.h>
44 #include "IPACM_Defs.h"
45 #include "IPACM_Log.h"
46 
47 
IPACM_Neighbor()48 IPACM_Neighbor::IPACM_Neighbor()
49 {
50 	num_neighbor_client = 0;
51 	circular_index = 0;
52 	memset(neighbor_client, 0, IPA_MAX_NUM_NEIGHBOR_CLIENTS * sizeof(ipa_neighbor_client));
53 	IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_ADD_EVENT_EX, this);
54 	IPACM_EvtDispatcher::registr(IPA_NEW_NEIGH_EVENT, this);
55 	IPACM_EvtDispatcher::registr(IPA_DEL_NEIGH_EVENT, this);
56 	return;
57 }
58 
event_callback(ipa_cm_event_id event,void * param)59 void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param)
60 {
61 	ipacm_event_data_all *data_all = NULL;
62 	int i, ipa_interface_index;
63 	ipacm_cmd_q_data evt_data;
64 	int num_neighbor_client_temp = num_neighbor_client;
65 
66 	IPACMDBG("Recieved event %d\n", event);
67 
68 	switch (event)
69 	{
70 		case IPA_WLAN_CLIENT_ADD_EVENT_EX:
71 		{
72 			ipacm_event_data_wlan_ex *data = (ipacm_event_data_wlan_ex *)param;
73 			ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index);
74 			/* check for failure return */
75 			if (IPACM_FAILURE == ipa_interface_index) {
76 				IPACMERR("IPA_WLAN_CLIENT_ADD_EVENT_EX: not supported iface id: %d\n", data->if_index);
77 				break;
78 			}
79 			uint8_t client_mac_addr[6] = {0};
80 
81 			IPACMDBG_H("Received IPA_WLAN_CLIENT_ADD_EVENT\n");
82 			for(i = 0; i < data->num_of_attribs; i++)
83 			{
84 				if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR)
85 				{
86 					memcpy(client_mac_addr,
87 							data->attribs[i].u.mac_addr,
88 							sizeof(client_mac_addr));
89 					IPACMDBG_H("AP Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n",
90 							 client_mac_addr[0], client_mac_addr[1], client_mac_addr[2],
91 							 client_mac_addr[3], client_mac_addr[4], client_mac_addr[5]);
92 				}
93 				else
94 				{
95 					IPACMDBG_H("The attribute type is not expected!\n");
96 				}
97 			}
98 
99 			for (i = 0; i < num_neighbor_client_temp; i++)
100 			{
101 				/* find the client */
102 				if (memcmp(neighbor_client[i].mac_addr, client_mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0)
103 				{
104 					/* check if iface is not bridge interface*/
105 					if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) != 0)
106 					{
107 						/* use previous ipv4 first */
108 						if(data->if_index != neighbor_client[i].iface_index)
109 						{
110 							IPACMERR("update new kernel iface index \n");
111 							neighbor_client[i].iface_index = data->if_index;
112 						}
113 
114 						/* check if client associated with previous network interface */
115 						if(ipa_interface_index != neighbor_client[i].ipa_if_num)
116 						{
117 							IPACMERR("client associate to different AP \n");
118 							return;
119 						}
120 
121 						if (neighbor_client[i].v4_addr != 0) /* not 0.0.0.0 */
122 						{
123 							evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
124 							data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
125 							if (data_all == NULL)
126 							{
127 								IPACMERR("Unable to allocate memory\n");
128 								return;
129 							}
130 							data_all->iptype = IPA_IP_v4;
131 							data_all->if_index = neighbor_client[i].iface_index;
132 							data_all->ipv4_addr = neighbor_client[i].v4_addr; //use previous ipv4 address
133 							memcpy(data_all->mac_addr,
134 									neighbor_client[i].mac_addr,
135 												sizeof(data_all->mac_addr));
136 							evt_data.evt_data = (void *)data_all;
137 							IPACM_EvtDispatcher::PostEvt(&evt_data);
138 							/* ask for replaced iface name*/
139 							ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index);
140 							/* check for failure return */
141 							if (IPACM_FAILURE == ipa_interface_index) {
142 								IPACMERR("not supported iface id: %d\n", data_all->if_index);
143 							} else {
144 								IPACMDBG_H("Posted event %d, with %s for ipv4 client re-connect\n",
145 									evt_data.event,
146 									IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
147 							}
148 						}
149 					}
150 					break;
151 				}
152 			}
153 		}
154 		break;
155 
156 		default:
157 		{
158 			if (event == IPA_NEW_NEIGH_EVENT)
159 			{
160 				IPACMDBG_H("Received IPA_NEW_NEIGH_EVENT\n");
161 			}
162 			else
163 			{
164 				IPACMDBG_H("Received IPA_DEL_NEIGH_EVENT\n");
165 			}
166 
167 			ipacm_event_data_all *data = (ipacm_event_data_all *)param;
168 			ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index);
169 			/* check for failure return */
170 			if (IPACM_FAILURE == ipa_interface_index) {
171 				IPACMERR("not supported iface id: %d\n", data->if_index);
172 				break;
173 			}
174 			if (data->iptype == IPA_IP_v4)
175 			{
176 				if (data->ipv4_addr != 0) /* not 0.0.0.0 */
177 				{
178 					IPACMDBG("Got Neighbor event with ipv4 address: 0x%x \n", data->ipv4_addr);
179 					/* check if ipv4 address is link local(169.254.xxx.xxx) */
180 					if ((data->ipv4_addr & IPV4_ADDR_LINKLOCAL_MASK) == IPV4_ADDR_LINKLOCAL)
181 					{
182 						IPACMDBG_H("This is link local ipv4 address: 0x%x : ignore this NEIGH_EVENT\n", data->ipv4_addr);
183 						return;
184 					}
185 					/* check if iface is bridge interface*/
186 					if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0)
187 					{
188 						/* searh if seen this client or not*/
189 						for (i = 0; i < num_neighbor_client_temp; i++)
190 						{
191 							if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0)
192 							{
193 								data->if_index = neighbor_client[i].iface_index;
194 								neighbor_client[i].v4_addr = data->ipv4_addr; // cache client's previous ipv4 address
195 								/* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */
196 								if (event == IPA_NEW_NEIGH_EVENT)
197 									evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
198 								else
199 									/* not to clean-up the client mac cache on bridge0 delneigh */
200 									evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
201 								data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
202 								if (data_all == NULL)
203 								{
204 									IPACMERR("Unable to allocate memory\n");
205 									return;
206 								}
207 								memcpy(data_all, data, sizeof(ipacm_event_data_all));
208 								evt_data.evt_data = (void *)data_all;
209 								IPACM_EvtDispatcher::PostEvt(&evt_data);
210 
211 								/* ask for replaced iface name*/
212 								ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index);
213 								/* check for failure return */
214 								if (IPACM_FAILURE == ipa_interface_index) {
215 									IPACMERR("not supported iface id: %d\n", data_all->if_index);
216 								} else {
217 									IPACMDBG_H("Posted event %d,\
218 										with %s for ipv4\n",
219 										evt_data.event,
220 										IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
221 								}
222 								break;
223 							}
224 						}
225 					}
226 					else
227 					{
228 						/* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */
229 						if (event == IPA_NEW_NEIGH_EVENT)
230 						{
231 							evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
232 							/* Also save to cache for ipv4 */
233 							/*searh if seen this client or not*/
234 							for (i = 0; i < num_neighbor_client_temp; i++)
235 							{
236 								/* find the client */
237 								if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0)
238 								{
239 									/* update the network interface client associated */
240 									neighbor_client[i].iface_index = data->if_index;
241 									neighbor_client[i].ipa_if_num = ipa_interface_index;
242 									neighbor_client[i].v4_addr = data->ipv4_addr; // cache client's previous ipv4 address
243 									IPACMDBG_H("update cache %d-entry, with %s iface, ipv4 address: 0x%x\n",
244 													i,
245 													IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,
246 													data->ipv4_addr);
247 									break;
248 								}
249 							}
250 							/* not find client */
251 							if (i == num_neighbor_client_temp)
252 							{
253 								if (num_neighbor_client_temp < IPA_MAX_NUM_NEIGHBOR_CLIENTS)
254 								{
255 									memcpy(neighbor_client[num_neighbor_client_temp].mac_addr,
256 												data->mac_addr,
257 												sizeof(data->mac_addr));
258 									neighbor_client[num_neighbor_client_temp].iface_index = data->if_index;
259 									/* cache the network interface client associated */
260 									neighbor_client[num_neighbor_client_temp].ipa_if_num = ipa_interface_index;
261 									neighbor_client[num_neighbor_client_temp].v4_addr = data->ipv4_addr;
262 									num_neighbor_client++;
263 									IPACMDBG_H("Cache client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n",
264 												neighbor_client[num_neighbor_client_temp].mac_addr[0],
265 												neighbor_client[num_neighbor_client_temp].mac_addr[1],
266 												neighbor_client[num_neighbor_client_temp].mac_addr[2],
267 												neighbor_client[num_neighbor_client_temp].mac_addr[3],
268 												neighbor_client[num_neighbor_client_temp].mac_addr[4],
269 												neighbor_client[num_neighbor_client_temp].mac_addr[5],
270 												num_neighbor_client);
271 								}
272 								else
273 								{
274 
275 									IPACMERR("error:  neighbor client oversize! recycle %d-st entry ! \n", circular_index);
276 									memcpy(neighbor_client[circular_index].mac_addr,
277 												data->mac_addr,
278 												sizeof(data->mac_addr));
279 									neighbor_client[circular_index].iface_index = data->if_index;
280 									/* cache the network interface client associated */
281 									neighbor_client[circular_index].ipa_if_num = ipa_interface_index;
282 									neighbor_client[circular_index].v4_addr = 0;
283 									IPACMDBG_H("Copy wlan-iface client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d, circular %d\n",
284 													neighbor_client[circular_index].mac_addr[0],
285 													neighbor_client[circular_index].mac_addr[1],
286 													neighbor_client[circular_index].mac_addr[2],
287 													neighbor_client[circular_index].mac_addr[3],
288 													neighbor_client[circular_index].mac_addr[4],
289 													neighbor_client[circular_index].mac_addr[5],
290 													num_neighbor_client,
291 													circular_index);
292 									circular_index++;
293 								}
294 							}
295 						}
296 						else
297 						{
298 							evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
299 							/*searh if seen this client or not*/
300 							for (i = 0; i < num_neighbor_client_temp; i++)
301 							{
302 								/* find the client */
303 								if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0)
304 								{
305 									IPACMDBG_H("Clean %d-st Cached client-MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n",
306 												i,
307 												neighbor_client[i].mac_addr[0],
308 												neighbor_client[i].mac_addr[1],
309 												neighbor_client[i].mac_addr[2],
310 												neighbor_client[i].mac_addr[3],
311 												neighbor_client[i].mac_addr[4],
312 												neighbor_client[i].mac_addr[5],
313 												num_neighbor_client);
314 
315 									memset(neighbor_client[i].mac_addr, 0, sizeof(neighbor_client[i].mac_addr));
316 									neighbor_client[i].iface_index = 0;
317 									neighbor_client[i].v4_addr = 0;
318 									neighbor_client[i].ipa_if_num = 0;
319 									for (; i < num_neighbor_client_temp - 1; i++)
320 									{
321 										memcpy(neighbor_client[i].mac_addr,
322 													neighbor_client[i+1].mac_addr,
323 													sizeof(neighbor_client[i].mac_addr));
324 										neighbor_client[i].iface_index = neighbor_client[i+1].iface_index;
325 										neighbor_client[i].v4_addr = neighbor_client[i+1].v4_addr;
326 										neighbor_client[i].ipa_if_num = neighbor_client[i+1].ipa_if_num;
327 									}
328 									num_neighbor_client--;
329 									IPACMDBG_H(" total number of left cased clients: %d\n", num_neighbor_client);
330 									break;
331 								}
332 							}
333 							/* not find client, no need clean-up */
334 						}
335 
336 						data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
337 						if (data_all == NULL)
338 						{
339 							IPACMERR("Unable to allocate memory\n");
340 							return;
341 						}
342 						memcpy(data_all, data, sizeof(ipacm_event_data_all));
343 						evt_data.evt_data = (void *)data_all;
344 						IPACM_EvtDispatcher::PostEvt(&evt_data);
345 						IPACMDBG_H("Posted event %d with %s for ipv4\n",
346 									evt_data.event,
347 									IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
348 					}
349 				}
350 			}
351 			else
352 			{   //ipv6 starts
353 
354 				if ((data->ipv6_addr[0]) || (data->ipv6_addr[1]) || (data->ipv6_addr[2]) || (data->ipv6_addr[3]))
355 				{
356 					IPACMDBG("Got New_Neighbor event with ipv6 address \n");
357 					/* check if iface is bridge interface*/
358 					if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0)
359 					{
360 						/* searh if seen this client or not*/
361 						for (i = 0; i < num_neighbor_client_temp; i++)
362 						{
363 							if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0)
364 							{
365 								data->if_index = neighbor_client[i].iface_index;
366 								/* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */
367 								if (event == IPA_NEW_NEIGH_EVENT) evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
368 								else evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
369 								data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
370 								if (data_all == NULL)
371 								{
372 									IPACMERR("Unable to allocate memory\n");
373 									return;
374 								}
375 								memcpy(data_all, data, sizeof(ipacm_event_data_all));
376 								evt_data.evt_data = (void *)data_all;
377 								IPACM_EvtDispatcher::PostEvt(&evt_data);
378 								/* ask for replaced iface name*/
379 								ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index);
380 								/* check for failure return */
381 								if (IPACM_FAILURE == ipa_interface_index) {
382 									IPACMERR("not supported iface id: %d\n", data_all->if_index);
383 								} else {
384 									IPACMDBG_H("Posted event %d,\
385 										with %s for ipv6\n",
386 										evt_data.event,
387 										IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
388 								}
389 								break;
390 							};
391 						}
392 					}
393 					else
394 					{
395 						/* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */
396 						if (event == IPA_NEW_NEIGH_EVENT)
397 							evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
398 						else
399 							evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
400 						data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
401 						if (data_all == NULL)
402 						{
403 							IPACMERR("Unable to allocate memory\n");
404 							return;
405 						}
406 						memcpy(data_all, data, sizeof(ipacm_event_data_all));
407 						evt_data.evt_data = (void *)data_all;
408 						IPACM_EvtDispatcher::PostEvt(&evt_data);
409 						IPACMDBG_H("Posted event %d with %s for ipv6\n",
410 										evt_data.event,
411 										IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
412 					}
413 				}
414 				else
415 				{
416 					IPACMDBG(" Got Neighbor event with no ipv6/ipv4 address \n");
417 					/*no ipv6 in data searh if seen this client or not*/
418 					for (i = 0; i < num_neighbor_client_temp; i++)
419 					{
420 						/* find the client */
421 						if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0)
422 						{
423 							IPACMDBG_H(" find %d-st client, MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n",
424 												i,
425 												neighbor_client[i].mac_addr[0],
426 												neighbor_client[i].mac_addr[1],
427 												neighbor_client[i].mac_addr[2],
428 												neighbor_client[i].mac_addr[3],
429 												neighbor_client[i].mac_addr[4],
430 												neighbor_client[i].mac_addr[5],
431 												num_neighbor_client);
432 							/* check if iface is not bridge interface*/
433 							if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) != 0)
434 							{
435 								/* use previous ipv4 first */
436 								if(data->if_index != neighbor_client[i].iface_index)
437 								{
438 									IPACMDBG_H("update new kernel iface index \n");
439 									neighbor_client[i].iface_index = data->if_index;
440 								}
441 
442 								/* check if client associated with previous network interface */
443 								if(ipa_interface_index != neighbor_client[i].ipa_if_num)
444 								{
445 									IPACMDBG_H("client associate to different AP \n");
446 								}
447 
448 								if (neighbor_client[i].v4_addr != 0) /* not 0.0.0.0 */
449 								{
450 									/* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */
451 									if (event == IPA_NEW_NEIGH_EVENT)
452 										evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
453 									else
454 										evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
455 									data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
456 									if (data_all == NULL)
457 									{
458 										IPACMERR("Unable to allocate memory\n");
459 										return;
460 									}
461 									data_all->iptype = IPA_IP_v4;
462 									data_all->if_index = neighbor_client[i].iface_index;
463 									data_all->ipv4_addr = neighbor_client[i].v4_addr; //use previous ipv4 address
464 									memcpy(data_all->mac_addr,
465 											neighbor_client[i].mac_addr,
466 														sizeof(data_all->mac_addr));
467 									evt_data.evt_data = (void *)data_all;
468 									IPACM_EvtDispatcher::PostEvt(&evt_data);
469 									/* ask for replaced iface name*/
470 									ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index);
471 									/* check for failure return */
472 									if (IPACM_FAILURE == ipa_interface_index) {
473 										IPACMERR("not supported iface id: %d\n", data_all->if_index);
474 									} else {
475 										IPACMDBG_H("Posted event %d,\
476 											with %s for ipv4 client re-connect\n",
477 											evt_data.event,
478 											IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
479 									}
480 								}
481 							}
482 							/* delete cache neighbor entry */
483 							if (event == IPA_DEL_NEIGH_EVENT)
484 							{
485 								IPACMDBG_H("Clean %d-st Cached client-MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n",
486 										i,
487 										neighbor_client[i].mac_addr[0],
488 										neighbor_client[i].mac_addr[1],
489 										neighbor_client[i].mac_addr[2],
490 										neighbor_client[i].mac_addr[3],
491 										neighbor_client[i].mac_addr[4],
492 										neighbor_client[i].mac_addr[5],
493 										num_neighbor_client);
494 
495 								memset(neighbor_client[i].mac_addr, 0, sizeof(neighbor_client[i].mac_addr));
496 								neighbor_client[i].iface_index = 0;
497 								neighbor_client[i].v4_addr = 0;
498 								neighbor_client[i].ipa_if_num = 0;
499 								for (; i < num_neighbor_client_temp - 1; i++)
500 								{
501 									memcpy(neighbor_client[i].mac_addr,
502 												neighbor_client[i+1].mac_addr,
503 												sizeof(neighbor_client[i].mac_addr));
504 									neighbor_client[i].iface_index = neighbor_client[i+1].iface_index;
505 									neighbor_client[i].v4_addr = neighbor_client[i+1].v4_addr;
506 									neighbor_client[i].ipa_if_num = neighbor_client[i+1].ipa_if_num;
507 								}
508 								num_neighbor_client--;
509 								IPACMDBG_H(" total number of left cased clients: %d\n", num_neighbor_client);
510 							}
511 							break;
512 						}
513 					}
514 					/* not find client */
515 					if ((i == num_neighbor_client_temp) && (event == IPA_NEW_NEIGH_EVENT))
516 					{
517 						/* check if iface is not bridge interface*/
518 						if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) != 0)
519 						{
520 							if (num_neighbor_client_temp < IPA_MAX_NUM_NEIGHBOR_CLIENTS)
521 							{
522 								memcpy(neighbor_client[num_neighbor_client_temp].mac_addr,
523 											data->mac_addr,
524 											sizeof(data->mac_addr));
525 								neighbor_client[num_neighbor_client_temp].iface_index = data->if_index;
526 								/* cache the network interface client associated */
527 								neighbor_client[num_neighbor_client_temp].ipa_if_num = ipa_interface_index;
528 								neighbor_client[num_neighbor_client_temp].v4_addr = 0;
529 								num_neighbor_client++;
530 								IPACMDBG_H("Copy client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n",
531 												neighbor_client[num_neighbor_client_temp].mac_addr[0],
532 												neighbor_client[num_neighbor_client_temp].mac_addr[1],
533 												neighbor_client[num_neighbor_client_temp].mac_addr[2],
534 												neighbor_client[num_neighbor_client_temp].mac_addr[3],
535 												neighbor_client[num_neighbor_client_temp].mac_addr[4],
536 												neighbor_client[num_neighbor_client_temp].mac_addr[5],
537 												num_neighbor_client);
538 								return;
539 							}
540 							else
541 							{
542 								IPACMERR("error:  neighbor client oversize! recycle %d-st entry ! \n", circular_index);
543 								memcpy(neighbor_client[circular_index].mac_addr,
544 											data->mac_addr,
545 											sizeof(data->mac_addr));
546 								neighbor_client[circular_index].iface_index = data->if_index;
547 								/* cache the network interface client associated */
548 								neighbor_client[circular_index].ipa_if_num = ipa_interface_index;
549 								neighbor_client[circular_index].v4_addr = 0;
550 								IPACMDBG_H("Copy wlan-iface client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d, circular %d\n",
551 												neighbor_client[circular_index].mac_addr[0],
552 												neighbor_client[circular_index].mac_addr[1],
553 												neighbor_client[circular_index].mac_addr[2],
554 												neighbor_client[circular_index].mac_addr[3],
555 												neighbor_client[circular_index].mac_addr[4],
556 												neighbor_client[circular_index].mac_addr[5],
557 												num_neighbor_client,
558 												circular_index);
559 								circular_index++;
560 								return;
561 							}
562 						}
563 					}
564 				}
565 			} //ipv6 ends
566 		}
567 		break;
568 	}
569 	return;
570 }
571