1/*
2Copyright (c) 2013, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
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
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF 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
48IPACM_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
59void 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