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_Netlink.cpp
32
33	@brief
34	This file implements the IPAM Netlink Socket Parer functionality.
35
36	@Author
37	Skylar Chang
38
39*/
40#include <string.h>
41#include <unistd.h>
42#include <sys/ioctl.h>
43#include <netinet/in.h>
44#include "IPACM_CmdQueue.h"
45#include "IPACM_Defs.h"
46#include "IPACM_Netlink.h"
47#include "IPACM_EvtDispatcher.h"
48#include "IPACM_Log.h"
49
50int ipa_get_if_name(char *if_name, int if_index);
51int find_mask(int ip_v4_last, int *mask_value);
52
53#ifdef FEATURE_IPA_ANDROID
54
55#define IPACM_NL_COPY_ADDR( event_info, element )                                        \
56        memcpy( &event_info->attr_info.element.__data,                                   \
57                RTA_DATA(rtah),                                                          \
58                sizeof(event_info->attr_info.element.__data) );
59
60#define IPACM_EVENT_COPY_ADDR_v6( event_data, element)                                   \
61        memcpy( event_data, element.__data, sizeof(event_data));
62
63#define IPACM_EVENT_COPY_ADDR_v4( event_data, element)                                   \
64        memcpy( &event_data, element.__data, sizeof(event_data));
65
66#define IPACM_NL_REPORT_ADDR( prefix, addr )                                             \
67        if( AF_INET6 == (addr).ss_family ) {                                             \
68          IPACM_LOG_IPV6_ADDR( prefix, addr.__data);                                    \
69        } else {                                                                         \
70          IPACM_LOG_IPV4_ADDR( prefix, (*(unsigned int*)&(addr).__data) );               \
71        }
72
73#else/* defined(FEATURE_IPA_ANDROID) */
74
75#define IPACM_NL_COPY_ADDR( event_info, element )                                        \
76        memcpy( &event_info->attr_info.element.__ss_padding,                             \
77                RTA_DATA(rtah),                                                          \
78                sizeof(event_info->attr_info.element.__ss_padding) );
79
80#define IPACM_EVENT_COPY_ADDR_v6( event_data, element)                                   \
81        memcpy( event_data, element.__ss_padding, sizeof(event_data));
82
83#define IPACM_EVENT_COPY_ADDR_v4( event_data, element)                                   \
84        memcpy( &event_data, element.__ss_padding, sizeof(event_data));
85
86#define IPACM_NL_REPORT_ADDR( prefix, addr )                                             \
87        if( AF_INET6 == (addr).ss_family ) {                                             \
88          IPACM_LOG_IPV6_ADDR( prefix, addr.__ss_padding);                               \
89        } else {                                                                         \
90          IPACM_LOG_IPV4_ADDR( prefix, (*(unsigned int*)&(addr).__ss_padding) );         \
91        }
92#endif /* defined(FEATURE_IPA_ANDROID)*/
93
94#define NDA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
95#define IPACM_LOG_IPV6_ADDR(prefix, ip_addr)                            \
96        IPACMDBG_H(prefix);                                               \
97		IPACMDBG_H(" IPV6 Address %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", \
98                  (int)ip_addr[0],  (int)ip_addr[1],                                                        \
99                  (int)ip_addr[2],  (int)ip_addr[3],                                                        \
100                  (int)ip_addr[4],  (int)ip_addr[5],                                                        \
101                  (int)ip_addr[6],  (int)ip_addr[7],                                                        \
102                  (int)ip_addr[8],  (int)ip_addr[9],                                                        \
103                  (int)ip_addr[10], (int)ip_addr[11],                                                       \
104                  (int)ip_addr[12], (int)ip_addr[13],                                                       \
105                  (int)ip_addr[14], (int)ip_addr[15]);
106
107#define IPACM_LOG_IPV4_ADDR(prefix, ip_addr)                            \
108        IPACMDBG_H(prefix);                                               \
109        IPACMDBG_H(" IPV4 Address %d.%d.%d.%d\n",                         \
110                    (unsigned char)(ip_addr),                               \
111                    (unsigned char)(ip_addr >> 8),                          \
112                    (unsigned char)(ip_addr >> 16) ,                        \
113                    (unsigned char)(ip_addr >> 24));
114
115/* Opens a netlink socket*/
116static int ipa_nl_open_socket
117(
118	 ipa_nl_sk_info_t *sk_info,
119	 int protocol,
120	 unsigned int grps
121	 )
122{
123	int *p_sk_fd;
124	int buf_size = 6669999, sendbuff=0, res;
125	struct sockaddr_nl *p_sk_addr_loc;
126	socklen_t optlen;
127
128	p_sk_fd = &(sk_info->sk_fd);
129	p_sk_addr_loc = &(sk_info->sk_addr_loc);
130
131	/* Open netlink socket for specified protocol */
132	if((*p_sk_fd = socket(AF_NETLINK, SOCK_RAW, protocol)) < 0)
133	{
134		IPACMERR("cannot open netlink socket\n");
135		return IPACM_FAILURE;
136	}
137
138	optlen = sizeof(sendbuff);
139	res = getsockopt(*p_sk_fd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen);
140
141	if(res == -1) {
142		IPACMDBG("Error getsockopt one");
143	} else {
144		IPACMDBG("orignal send buffer size = %d\n", sendbuff);
145	}
146	IPACMDBG("sets the send buffer to %d\n", buf_size);
147	if (setsockopt(*p_sk_fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(int)) == -1) {
148    IPACMERR("Error setting socket opts\n");
149	}
150
151	/* Initialize socket addresses to null */
152	memset(p_sk_addr_loc, 0, sizeof(struct sockaddr_nl));
153
154	/* Populate local socket address using specified groups */
155	p_sk_addr_loc->nl_family = AF_NETLINK;
156	p_sk_addr_loc->nl_pid = getpid();
157	p_sk_addr_loc->nl_groups = grps;
158
159	/* Bind socket to the local address, i.e. specified groups. This ensures
160	 that multicast messages for these groups are delivered over this
161	 socket. */
162
163	if(bind(*p_sk_fd,
164					(struct sockaddr *)p_sk_addr_loc,
165					sizeof(struct sockaddr_nl)) < 0)
166	{
167		IPACMERR("Socket bind failed\n");
168		return IPACM_FAILURE;
169	}
170
171	return IPACM_SUCCESS;
172}
173
174/* Add fd to fdmap array and store read handler function ptr (up to MAX_NUM_OF_FD).*/
175static int ipa_nl_addfd_map
176(
177	 ipa_nl_sk_fd_set_info_t *info,
178	 int fd,
179	 ipa_sock_thrd_fd_read_f read_f
180	 )
181{
182	if(info->num_fd < MAX_NUM_OF_FD)
183	{
184		FD_SET(fd, &info->fdset);
185
186		/* Add fd to fdmap array and store read handler function ptr */
187		info->sk_fds[info->num_fd].sk_fd = fd;
188		info->sk_fds[info->num_fd].read_func = read_f;
189
190		/* Increment number of fds stored in fdmap */
191		info->num_fd++;
192		if(info->max_fd < fd)
193			info->max_fd = fd;
194	}
195	else
196	{
197		return IPACM_FAILURE;
198	}
199
200	return IPACM_SUCCESS;
201}
202
203/*  start socket listener */
204static int ipa_nl_sock_listener_start
205(
206	 ipa_nl_sk_fd_set_info_t *sk_fd_set
207	 )
208{
209	int i, ret;
210
211	while(true)
212	{
213	    for(i = 0; i < sk_fd_set->num_fd; i++ )
214		{
215			FD_SET(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset));
216		}
217
218		if((ret = select(sk_fd_set->max_fd + 1, &(sk_fd_set->fdset), NULL, NULL, NULL)) < 0)
219		{
220			IPACMERR("ipa_nl select failed\n");
221		}
222		else
223		{
224			for(i = 0; i < sk_fd_set->num_fd; i++)
225			{
226
227				if(FD_ISSET(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset)))
228				{
229
230					if(sk_fd_set->sk_fds[i].read_func)
231					{
232						if(IPACM_SUCCESS != ((sk_fd_set->sk_fds[i].read_func)(sk_fd_set->sk_fds[i].sk_fd)))
233						{
234							IPACMERR("Error on read callback[%d] fd=%d\n",
235											 i,
236											 sk_fd_set->sk_fds[i].sk_fd);
237						}
238						FD_CLR(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset));
239					}
240					else
241					{
242						IPACMERR("No read function\n");
243					}
244				}
245
246			} /* end of for loop*/
247		} /* end of else */
248	} /* end of while */
249
250	return IPACM_SUCCESS;
251}
252
253/* allocate memory for ipa_nl__msg */
254static struct msghdr* ipa_nl_alloc_msg
255(
256	 uint32_t msglen
257	 )
258{
259	unsigned char *buf = NULL;
260	struct sockaddr_nl *nladdr = NULL;
261	struct iovec *iov = NULL;
262	struct msghdr *msgh = NULL;
263
264	if(IPA_NL_MSG_MAX_LEN < msglen)
265	{
266		IPACMERR("Netlink message exceeds maximum length\n");
267		return NULL;
268	}
269
270	msgh = (struct msghdr *)malloc(sizeof(struct msghdr));
271	if(msgh == NULL)
272	{
273		IPACMERR("Failed malloc for msghdr\n");
274		return NULL;
275	}
276
277	nladdr = (struct sockaddr_nl *)malloc(sizeof(struct sockaddr_nl));
278	if(nladdr == NULL)
279	{
280		IPACMERR("Failed malloc for sockaddr\n");
281		free(msgh);
282		return NULL;
283	}
284
285	iov = (struct iovec *)malloc(sizeof(struct iovec));
286	if(iov == NULL)
287	{
288		PERROR("Failed malloc for iovec");
289		free(nladdr);
290		free(msgh);
291		return NULL;
292	}
293
294	buf = (unsigned char *)malloc(msglen);
295	if(buf == NULL)
296	{
297		IPACMERR("Failed malloc for mglen\n");
298		free(iov);
299		free(nladdr);
300		free(msgh);
301		return NULL;
302	}
303
304	memset(nladdr, 0, sizeof(struct sockaddr_nl));
305	nladdr->nl_family = AF_NETLINK;
306
307	memset(msgh, 0x0, sizeof(struct msghdr));
308	msgh->msg_name = nladdr;
309	msgh->msg_namelen = sizeof(struct sockaddr_nl);
310	msgh->msg_iov = iov;
311	msgh->msg_iovlen = 1;
312
313	memset(iov, 0x0, sizeof(struct iovec));
314	iov->iov_base = buf;
315	iov->iov_len = msglen;
316
317	return msgh;
318}
319
320/* release IPA message */
321static void ipa_nl_release_msg
322(
323	 struct msghdr *msgh
324	 )
325{
326	unsigned char *buf = NULL;
327	struct sockaddr_nl *nladdr = NULL;
328	struct iovec *iov = NULL;
329
330	if(NULL == msgh)
331	{
332		return;
333	}
334
335	nladdr = (struct sockaddr_nl *)msgh->msg_name;
336	iov = msgh->msg_iov;
337	if(msgh->msg_iov)
338	{
339		buf = (unsigned char *)msgh->msg_iov->iov_base;
340	}
341
342	if(buf)
343	{
344	free(buf);
345	}
346	if(iov)
347	{
348	free(iov);
349	}
350	if(nladdr)
351	{
352	free(nladdr);
353	}
354	if(msgh)
355	{
356	free(msgh);
357	}
358	return;
359}
360
361/* receive and process nl message */
362static int ipa_nl_recv
363(
364	 int              fd,
365	 struct msghdr **msg_pptr,
366	 unsigned int  *msglen_ptr
367	 )
368{
369	struct msghdr *msgh = NULL;
370	int rmsgl;
371
372	msgh = ipa_nl_alloc_msg(IPA_NL_MSG_MAX_LEN);
373	if(NULL == msgh)
374	{
375		IPACMERR("Failed to allocate NL message\n");
376		goto error;
377	}
378
379
380	/* Receive message over the socket */
381	rmsgl = recvmsg(fd, msgh, 0);
382
383	/* Verify that something was read */
384	if(rmsgl <= 0)
385	{
386		PERROR("NL recv error");
387		goto error;
388	}
389
390	/* Verify that NL address length in the received message is expected value */
391	if(sizeof(struct sockaddr_nl) != msgh->msg_namelen)
392	{
393		IPACMERR("rcvd msg with namelen != sizeof sockaddr_nl\n");
394		goto error;
395	}
396
397	/* Verify that message was not truncated. This should not occur */
398	if(msgh->msg_flags & MSG_TRUNC)
399	{
400		IPACMERR("Rcvd msg truncated!\n");
401		goto error;
402	}
403
404	*msg_pptr    = msgh;
405	*msglen_ptr = rmsgl;
406
407	return IPACM_SUCCESS;
408
409/* An error occurred while receiving the message. Free all memory before
410				 returning. */
411error:
412	ipa_nl_release_msg(msgh);
413	*msg_pptr    = NULL;
414	*msglen_ptr  = 0;
415
416	return IPACM_FAILURE;
417}
418
419/* decode the rtm netlink message */
420static int ipa_nl_decode_rtm_link
421(
422	 const char              *buffer,
423	 unsigned int             buflen,
424	 ipa_nl_link_info_t      *link_info
425)
426{
427	struct rtattr;
428	/* NL message header */
429	struct nlmsghdr *nlh = (struct nlmsghdr *)buffer;
430
431	/* Extract the header data */
432	link_info->metainfo = *(struct ifinfomsg *)NLMSG_DATA(nlh);
433	buflen -= sizeof(struct nlmsghdr);
434
435	return IPACM_SUCCESS;
436}
437
438/* Decode kernel address message parameters from Netlink attribute TLVs. */
439static int ipa_nl_decode_rtm_addr
440(
441	 const char              *buffer,
442	 unsigned int             buflen,
443	 ipa_nl_addr_info_t   *addr_info
444	 )
445{
446	struct nlmsghdr *nlh = (struct nlmsghdr *)buffer;  /* NL message header */
447	struct rtattr *rtah = NULL;
448
449	/* Extract the header data */
450	addr_info->metainfo = *((struct ifaddrmsg *)NLMSG_DATA(nlh));
451	buflen -= sizeof(struct nlmsghdr);
452
453	/* Extract the available attributes */
454	addr_info->attr_info.param_mask = IPA_NLA_PARAM_NONE;
455
456	rtah = IFA_RTA(NLMSG_DATA(nlh));
457
458	while(RTA_OK(rtah, buflen))
459	{
460		switch(rtah->rta_type)
461		{
462
463		case IFA_ADDRESS:
464			addr_info->attr_info.prefix_addr.ss_family = addr_info->metainfo.ifa_family;
465			IPACM_NL_COPY_ADDR( addr_info, prefix_addr );
466			addr_info->attr_info.param_mask |= IPA_NLA_PARAM_PREFIXADDR;
467			break;
468		default:
469			break;
470
471		}
472		/* Advance to next attribute */
473		rtah = RTA_NEXT(rtah, buflen);
474	}
475
476	return IPACM_SUCCESS;
477}
478
479/* Decode kernel neighbor message parameters from Netlink attribute TLVs. */
480static int ipa_nl_decode_rtm_neigh
481(
482	 const char              *buffer,
483	 unsigned int             buflen,
484	 ipa_nl_neigh_info_t   *neigh_info
485	 )
486{
487	struct nlmsghdr *nlh = (struct nlmsghdr *)buffer;  /* NL message header */
488	struct rtattr *rtah = NULL;
489
490	/* Extract the header data */
491	neigh_info->metainfo = *((struct ndmsg *)NLMSG_DATA(nlh));
492	buflen -= sizeof(struct nlmsghdr);
493
494	/* Extract the available attributes */
495	neigh_info->attr_info.param_mask = IPA_NLA_PARAM_NONE;
496
497	rtah = NDA_RTA(NLMSG_DATA(nlh));
498
499	while(RTA_OK(rtah, buflen))
500	{
501		switch(rtah->rta_type)
502		{
503
504		case NDA_DST:
505			neigh_info->attr_info.local_addr.ss_family = neigh_info->metainfo.ndm_family;
506			IPACM_NL_COPY_ADDR( neigh_info, local_addr );
507			break;
508
509		case NDA_LLADDR:
510			memcpy(neigh_info->attr_info.lladdr_hwaddr.sa_data,
511						 RTA_DATA(rtah),
512						 sizeof(neigh_info->attr_info.lladdr_hwaddr.sa_data));
513			break;
514
515		default:
516			break;
517
518		}
519
520		/* Advance to next attribute */
521		rtah = RTA_NEXT(rtah, buflen);
522	}
523
524	return IPACM_SUCCESS;
525}
526
527/* Decode kernel route message parameters from Netlink attribute TLVs. */
528static int ipa_nl_decode_rtm_route
529(
530	 const char              *buffer,
531	 unsigned int             buflen,
532	 ipa_nl_route_info_t   *route_info
533	 )
534{
535	struct nlmsghdr *nlh = (struct nlmsghdr *)buffer;  /* NL message header */
536	struct rtattr *rtah = NULL;
537
538	/* Extract the header data */
539	route_info->metainfo = *((struct rtmsg *)NLMSG_DATA(nlh));
540	buflen -= sizeof(struct nlmsghdr);
541
542	route_info->attr_info.param_mask = IPA_RTA_PARAM_NONE;
543	rtah = RTM_RTA(NLMSG_DATA(nlh));
544
545	while(RTA_OK(rtah, buflen))
546	{
547		switch(rtah->rta_type)
548		{
549
550		case RTA_DST:
551				route_info->attr_info.dst_addr.ss_family = route_info->metainfo.rtm_family;
552				IPACM_NL_COPY_ADDR( route_info, dst_addr );
553				route_info->attr_info.param_mask |= IPA_RTA_PARAM_DST;
554			break;
555
556		case RTA_SRC:
557			route_info->attr_info.src_addr.ss_family = route_info->metainfo.rtm_family;
558			IPACM_NL_COPY_ADDR( route_info, src_addr );
559			route_info->attr_info.param_mask |= IPA_RTA_PARAM_SRC;
560			break;
561
562		case RTA_GATEWAY:
563			route_info->attr_info.gateway_addr.ss_family = route_info->metainfo.rtm_family;
564			IPACM_NL_COPY_ADDR( route_info, gateway_addr );
565			route_info->attr_info.param_mask |= IPA_RTA_PARAM_GATEWAY;
566			break;
567
568		case RTA_IIF:
569			memcpy(&route_info->attr_info.iif_index,
570						 RTA_DATA(rtah),
571						 sizeof(route_info->attr_info.iif_index));
572			route_info->attr_info.param_mask |= IPA_RTA_PARAM_IIF;
573			break;
574
575		case RTA_OIF:
576			memcpy(&route_info->attr_info.oif_index,
577						 RTA_DATA(rtah),
578						 sizeof(route_info->attr_info.oif_index));
579			route_info->attr_info.param_mask |= IPA_RTA_PARAM_OIF;
580			break;
581
582		case RTA_PRIORITY:
583			memcpy(&route_info->attr_info.priority,
584						 RTA_DATA(rtah),
585						 sizeof(route_info->attr_info.priority));
586			route_info->attr_info.param_mask |= IPA_RTA_PARAM_PRIORITY;
587			break;
588
589		default:
590			break;
591
592		}
593
594		/* Advance to next attribute */
595		rtah = RTA_NEXT(rtah, buflen);
596	}
597
598	return IPACM_SUCCESS;
599}
600
601/* decode the ipa nl-message */
602static int ipa_nl_decode_nlmsg
603(
604	 const char   *buffer,
605	 unsigned int  buflen,
606	 ipa_nl_msg_t  *msg_ptr
607	 )
608{
609	char dev_name[IF_NAME_LEN]={0};
610	int ret_val, mask_index, mask_value_v6;
611	struct nlmsghdr *nlh = (struct nlmsghdr *)buffer;
612
613	uint32_t if_ipv4_addr =0, if_ipipv4_addr_mask =0, temp =0, if_ipv4_addr_gw =0;
614
615	ipacm_cmd_q_data evt_data;
616	ipacm_event_data_all *data_all;
617	ipacm_event_data_fid *data_fid;
618	ipacm_event_data_addr *data_addr;
619
620
621	while(NLMSG_OK(nlh, buflen))
622	{
623		memset(dev_name,0,IF_NAME_LEN);
624		IPACMDBG("Received msg:%d from netlink\n", nlh->nlmsg_type)
625		switch(nlh->nlmsg_type)
626		{
627		case RTM_NEWLINK:
628			msg_ptr->type = nlh->nlmsg_type;
629			msg_ptr->link_event = true;
630			if(IPACM_SUCCESS != ipa_nl_decode_rtm_link(buffer, buflen, &(msg_ptr->nl_link_info)))
631			{
632				IPACMERR("Failed to decode rtm link message\n");
633				return IPACM_FAILURE;
634			}
635			else
636			{
637				IPACMDBG("Got RTM_NEWLINK with below values\n");
638				IPACMDBG("RTM_NEWLINK, ifi_change:%d\n", msg_ptr->nl_link_info.metainfo.ifi_change);
639				IPACMDBG("RTM_NEWLINK, ifi_flags:%d\n", msg_ptr->nl_link_info.metainfo.ifi_flags);
640				IPACMDBG("RTM_NEWLINK, ifi_index:%d\n", msg_ptr->nl_link_info.metainfo.ifi_index);
641				IPACMDBG("RTM_NEWLINK, family:%d\n", msg_ptr->nl_link_info.metainfo.ifi_family);
642				/* RTM_NEWLINK event with AF_BRIDGE family should be ignored in Android
643				   but this should be processed in case of MDM for Ehernet interface.
644				*/
645#ifdef FEATURE_IPA_ANDROID
646				if (msg_ptr->nl_link_info.metainfo.ifi_family == AF_BRIDGE)
647				{
648					IPACMERR(" ignore this RTM_NEWLINK msg \n");
649					return IPACM_SUCCESS;
650				}
651#endif
652				if(IFF_UP & msg_ptr->nl_link_info.metainfo.ifi_change)
653				{
654					IPACMDBG("GOT useful newlink event\n");
655					ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index);
656					if(ret_val != IPACM_SUCCESS)
657					{
658						IPACMERR("Error while getting interface name\n");
659						return IPACM_FAILURE;
660					}
661
662					data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
663					if(data_fid == NULL)
664					{
665						IPACMERR("unable to allocate memory for event data_fid\n");
666						return IPACM_FAILURE;
667					}
668					data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index;
669
670					if(msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_UP)
671					{
672						IPACMDBG_H("Interface %s bring up with IP-family: %d \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_family);
673						/* post link up to command queue */
674						evt_data.event = IPA_LINK_UP_EVENT;
675						IPACMDBG_H("Posting IPA_LINK_UP_EVENT with if index: %d\n",
676										 msg_ptr->nl_link_info.metainfo.ifi_index);
677					}
678					else
679					{
680						IPACMDBG_H("Interface %s bring down with IP-family: %d \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_family);
681						/* post link down to command queue */
682						evt_data.event = IPA_LINK_DOWN_EVENT;
683						IPACMDBG_H("Posting IPA_LINK_DOWN_EVENT with if index: %d\n",
684										 data_fid->if_index);
685					}
686					evt_data.evt_data = data_fid;
687					IPACM_EvtDispatcher::PostEvt(&evt_data);
688				}
689
690				/* Add IPACM support for ECM plug-in/plug_out */
691				/*--------------------------------------------------------------------------
692                   Check if the interface is running.If its a RTM_NEWLINK and the interface
693                    is running then it means that its a link up event
694                ---------------------------------------------------------------------------*/
695                if((msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_RUNNING) &&
696                   (msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_LOWER_UP))
697                {
698
699					data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
700					if(data_fid == NULL)
701					{
702						IPACMERR("unable to allocate memory for event data_fid\n");
703						return IPACM_FAILURE;
704					}
705					data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index;
706
707				        ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index);
708					if(ret_val != IPACM_SUCCESS)
709					{
710						IPACMERR("Error while getting interface name\n");
711						return IPACM_FAILURE;
712					}
713					IPACMDBG("Got a usb link_up event (Interface %s, %d) \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_index);
714
715                    /*--------------------------------------------------------------------------
716                       Post LAN iface (ECM) link up event
717                     ---------------------------------------------------------------------------*/
718                    evt_data.event = IPA_USB_LINK_UP_EVENT;
719					evt_data.evt_data = data_fid;
720					IPACMDBG_H("Posting usb IPA_LINK_UP_EVENT with if index: %d\n",
721										 data_fid->if_index);
722					IPACM_EvtDispatcher::PostEvt(&evt_data);
723                }
724                else if (!(msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_LOWER_UP))
725				{
726					data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
727					if(data_fid == NULL)
728					{
729						IPACMERR("unable to allocate memory for event data_fid\n");
730						return IPACM_FAILURE;
731					}
732					data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index;
733
734					ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index);
735					if(ret_val != IPACM_SUCCESS)
736					{
737						IPACMERR("Error while getting interface name\n");
738						return IPACM_FAILURE;
739					}
740					IPACMDBG_H("Got a usb link_down event (Interface %s) \n", dev_name);
741
742					/*--------------------------------------------------------------------------
743						Post LAN iface (ECM) link down event
744					---------------------------------------------------------------------------*/
745					evt_data.event = IPA_LINK_DOWN_EVENT;
746					evt_data.evt_data = data_fid;
747					IPACMDBG_H("Posting usb IPA_LINK_DOWN_EVENT with if index: %d\n",
748										 data_fid->if_index);
749					IPACM_EvtDispatcher::PostEvt(&evt_data);
750				}
751			}
752			break;
753
754		case RTM_DELLINK:
755			IPACMDBG("\n GOT dellink event\n");
756			msg_ptr->type = nlh->nlmsg_type;
757			msg_ptr->link_event = true;
758			IPACMDBG("entering rtm decode\n");
759			if(IPACM_SUCCESS != ipa_nl_decode_rtm_link(buffer, buflen, &(msg_ptr->nl_link_info)))
760			{
761				IPACMERR("Failed to decode rtm link message\n");
762				return IPACM_FAILURE;
763			}
764			else
765			{
766				IPACMDBG("Got RTM_DELLINK with below values\n");
767				IPACMDBG("RTM_DELLINK, ifi_change:%d\n", msg_ptr->nl_link_info.metainfo.ifi_change);
768				IPACMDBG("RTM_DELLINK, ifi_flags:%d\n", msg_ptr->nl_link_info.metainfo.ifi_flags);
769				IPACMDBG("RTM_DELLINK, ifi_index:%d\n", msg_ptr->nl_link_info.metainfo.ifi_index);
770				IPACMDBG("RTM_DELLINK, family:%d\n", msg_ptr->nl_link_info.metainfo.ifi_family);
771				/* RTM_NEWLINK event with AF_BRIDGE family should be ignored in Android
772				   but this should be processed in case of MDM for Ehernet interface.
773				*/
774#ifdef FEATURE_IPA_ANDROID
775				if (msg_ptr->nl_link_info.metainfo.ifi_family == AF_BRIDGE)
776				{
777					IPACMERR(" ignore this RTM_DELLINK msg \n");
778					return IPACM_SUCCESS;
779				}
780#endif
781				ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index);
782				if(ret_val != IPACM_SUCCESS)
783				{
784					IPACMERR("Error while getting interface name\n");
785					return IPACM_FAILURE;
786				}
787				IPACMDBG("Interface %s bring down \n", dev_name);
788
789				/* post link down to command queue */
790				evt_data.event = IPA_LINK_DOWN_EVENT;
791				data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
792				if(data_fid == NULL)
793				{
794					IPACMERR("unable to allocate memory for event data_fid\n");
795					return IPACM_FAILURE;
796				}
797
798				data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index;
799
800				IPACMDBG_H("posting IPA_LINK_DOWN_EVENT with if idnex:%d\n",
801								 data_fid->if_index);
802				evt_data.evt_data = data_fid;
803				IPACM_EvtDispatcher::PostEvt(&evt_data);
804				/* finish command queue */
805			}
806			break;
807
808		case RTM_NEWADDR:
809			IPACMDBG("\n GOT RTM_NEWADDR event\n");
810			if(IPACM_SUCCESS != ipa_nl_decode_rtm_addr(buffer, buflen, &(msg_ptr->nl_addr_info)))
811			{
812				IPACMERR("Failed to decode rtm addr message\n");
813				return IPACM_FAILURE;
814			}
815			else
816			{
817				ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_addr_info.metainfo.ifa_index);
818				if(ret_val != IPACM_SUCCESS)
819				{
820					IPACMERR("Error while getting interface name\n");
821				}
822				IPACMDBG("Interface %s \n", dev_name);
823
824				data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
825				if(data_addr == NULL)
826				{
827					IPACMERR("unable to allocate memory for event data_addr\n");
828					return IPACM_FAILURE;
829				}
830
831				if(AF_INET6 == msg_ptr->nl_addr_info.attr_info.prefix_addr.ss_family)
832				{
833					data_addr->iptype = IPA_IP_v6;
834					IPACM_NL_REPORT_ADDR( "IFA_ADDRESS:", msg_ptr->nl_addr_info.attr_info.prefix_addr );
835					IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_addr_info.attr_info.prefix_addr);
836					data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]);
837					data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
838					data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
839					data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
840				}
841				else
842				{
843					data_addr->iptype = IPA_IP_v4;
844					IPACM_NL_REPORT_ADDR( "IFA_ADDRESS:", msg_ptr->nl_addr_info.attr_info.prefix_addr );
845					IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr, msg_ptr->nl_addr_info.attr_info.prefix_addr);
846					data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr);
847
848				}
849
850				evt_data.event = IPA_ADDR_ADD_EVENT;
851				data_addr->if_index = msg_ptr->nl_addr_info.metainfo.ifa_index;
852				if(AF_INET6 == msg_ptr->nl_addr_info.attr_info.prefix_addr.ss_family)
853				{
854				    IPACMDBG("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv6 addr:0x%x:%x:%x:%x\n",
855								 data_addr->if_index,
856								 data_addr->ipv6_addr[0],
857								 data_addr->ipv6_addr[1],
858								 data_addr->ipv6_addr[2],
859								 data_addr->ipv6_addr[3]);
860                }
861				else
862				{
863				IPACMDBG("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv4 addr:0x%x\n",
864								 data_addr->if_index,
865								 data_addr->ipv4_addr);
866				}
867				evt_data.evt_data = data_addr;
868				IPACM_EvtDispatcher::PostEvt(&evt_data);
869			}
870			break;
871
872		case RTM_NEWROUTE:
873
874			if(IPACM_SUCCESS != ipa_nl_decode_rtm_route(buffer, buflen, &(msg_ptr->nl_route_info)))
875			{
876				IPACMERR("Failed to decode rtm route message\n");
877				return IPACM_FAILURE;
878			}
879
880			IPACMDBG("In case RTM_NEWROUTE\n");
881			IPACMDBG("rtm_type: %d\n", msg_ptr->nl_route_info.metainfo.rtm_type);
882			IPACMDBG("protocol: %d\n", msg_ptr->nl_route_info.metainfo.rtm_protocol);
883			IPACMDBG("rtm_scope: %d\n", msg_ptr->nl_route_info.metainfo.rtm_scope);
884			IPACMDBG("rtm_table: %d\n", msg_ptr->nl_route_info.metainfo.rtm_table);
885			IPACMDBG("rtm_family: %d\n", msg_ptr->nl_route_info.metainfo.rtm_family);
886			IPACMDBG("param_mask: 0x%x\n", msg_ptr->nl_route_info.attr_info.param_mask);
887
888			/* take care of route add default route & uniroute */
889			if((msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) &&
890				 ((msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) ||
891				  (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_RA)) &&
892				 (msg_ptr->nl_route_info.metainfo.rtm_scope == RT_SCOPE_UNIVERSE) &&
893				 (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN))
894			{
895				IPACMDBG("\n GOT RTM_NEWROUTE event\n");
896
897				if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST)
898				{
899					ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index);
900					if(ret_val != IPACM_SUCCESS)
901					{
902						IPACMERR("Error while getting interface name\n");
903						return IPACM_FAILURE;
904					}
905
906					IPACM_NL_REPORT_ADDR( "route add -host", msg_ptr->nl_route_info.attr_info.dst_addr );
907					IPACM_NL_REPORT_ADDR( "gw", msg_ptr->nl_route_info.attr_info.gateway_addr );
908					IPACMDBG("dev %s\n",dev_name );
909					/* insert to command queue */
910					IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr);
911					temp = (-1);
912
913					evt_data.event = IPA_ROUTE_ADD_EVENT;
914					data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
915					if(data_addr == NULL)
916					{
917						IPACMERR("unable to allocate memory for event data_addr\n");
918						return IPACM_FAILURE;
919					}
920
921					data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index;
922					data_addr->iptype = IPA_IP_v4;
923					data_addr->ipv4_addr = ntohl(if_ipv4_addr);
924					data_addr->ipv4_addr_mask = ntohl(if_ipipv4_addr_mask);
925
926					IPACMDBG("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv4 address 0x%x, mask:0x%x\n",
927									 data_addr->if_index,
928									 data_addr->ipv4_addr,
929									 data_addr->ipv4_addr_mask);
930					evt_data.evt_data = data_addr;
931					IPACM_EvtDispatcher::PostEvt(&evt_data);
932					/* finish command queue */
933
934				}
935				else
936				{
937					ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index);
938					if(ret_val != IPACM_SUCCESS)
939					{
940						IPACMERR("Error while getting interface name\n");
941						return IPACM_FAILURE;
942					}
943
944					if(AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family)
945					{
946						/* insert to command queue */
947						data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
948						if(data_addr == NULL)
949						{
950							IPACMERR("unable to allocate memory for event data_addr\n");
951							return IPACM_FAILURE;
952						}
953
954						if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_PRIORITY)
955						{
956							IPACMDBG_H("ip -6 route add default dev %s metric %d\n",
957											 dev_name,
958											 msg_ptr->nl_route_info.attr_info.priority);
959						}
960						else
961						{
962							IPACMDBG_H("ip -6 route add default dev %s\n", dev_name);
963						}
964
965						IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr);
966						data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]);
967						data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
968						data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
969						data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
970
971						IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr);
972						data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]);
973						data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]);
974						data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]);
975						data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]);
976
977						IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr);
978						data_addr->ipv6_addr_gw[0] = ntohl(data_addr->ipv6_addr_gw[0]);
979						data_addr->ipv6_addr_gw[1] = ntohl(data_addr->ipv6_addr_gw[1]);
980						data_addr->ipv6_addr_gw[2] = ntohl(data_addr->ipv6_addr_gw[2]);
981						data_addr->ipv6_addr_gw[3] = ntohl(data_addr->ipv6_addr_gw[3]);
982						IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_route_info.attr_info.gateway_addr);
983
984						evt_data.event = IPA_ROUTE_ADD_EVENT;
985						data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index;
986						data_addr->iptype = IPA_IP_v6;
987
988						IPACMDBG("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv6 address\n",
989										 data_addr->if_index);
990						evt_data.evt_data = data_addr;
991						IPACM_EvtDispatcher::PostEvt(&evt_data);
992						/* finish command queue */
993
994					}
995					else
996					{
997						IPACM_NL_REPORT_ADDR( "route add default gw \n", msg_ptr->nl_route_info.attr_info.gateway_addr );
998						IPACMDBG_H("dev %s \n", dev_name);
999						IPACM_NL_REPORT_ADDR( "dstIP:", msg_ptr->nl_route_info.attr_info.dst_addr );
1000
1001						/* insert to command queue */
1002						data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
1003						if(data_addr == NULL)
1004						{
1005							IPACMERR("unable to allocate memory for event data_addr\n");
1006							return IPACM_FAILURE;
1007						}
1008
1009						IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr);
1010						IPACM_EVENT_COPY_ADDR_v4( if_ipipv4_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr);
1011						IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr);
1012
1013						evt_data.event = IPA_ROUTE_ADD_EVENT;
1014						data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index;
1015						data_addr->iptype = IPA_IP_v4;
1016						data_addr->ipv4_addr = ntohl(if_ipv4_addr);
1017						data_addr->ipv4_addr_gw = ntohl(if_ipv4_addr_gw);
1018						data_addr->ipv4_addr_mask = ntohl(if_ipipv4_addr_mask);
1019
1020            IPACMDBG_H("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv4 addr:0x%x, mask: 0x%x and gw: 0x%x\n",
1021										 data_addr->if_index,
1022										 data_addr->ipv4_addr,
1023										 data_addr->ipv4_addr_mask,
1024										 data_addr->ipv4_addr_gw);
1025						evt_data.evt_data = data_addr;
1026						IPACM_EvtDispatcher::PostEvt(&evt_data);
1027						/* finish command queue */
1028					}
1029				}
1030			}
1031
1032			/* ipv6 routing table */
1033			if((AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) &&
1034				 (msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) &&
1035				 (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_KERNEL) &&
1036				 (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN))
1037			{
1038				IPACMDBG("\n GOT valid v6-RTM_NEWROUTE event\n");
1039				ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index);
1040				if(ret_val != IPACM_SUCCESS)
1041				{
1042					IPACMERR("Error while getting interface name\n");
1043					return IPACM_FAILURE;
1044				}
1045
1046				if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST)
1047				{
1048					IPACM_NL_REPORT_ADDR( "Route ADD DST:", msg_ptr->nl_route_info.attr_info.dst_addr );
1049					IPACMDBG("%d, metric %d, dev %s\n",
1050									 msg_ptr->nl_route_info.metainfo.rtm_dst_len,
1051									 msg_ptr->nl_route_info.attr_info.priority,
1052									 dev_name);
1053
1054					/* insert to command queue */
1055					data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
1056					if(data_addr == NULL)
1057					{
1058						IPACMERR("unable to allocate memory for event data_addr\n");
1059						return IPACM_FAILURE;
1060					}
1061
1062					 IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr);
1063
1064					data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]);
1065					data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
1066					data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
1067					data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
1068
1069					mask_value_v6 = msg_ptr->nl_route_info.metainfo.rtm_dst_len;
1070					for(mask_index = 0; mask_index < 4; mask_index++)
1071					{
1072						if(mask_value_v6 >= 32)
1073						{
1074							mask_v6(32, &data_addr->ipv6_addr_mask[mask_index]);
1075							mask_value_v6 -= 32;
1076						}
1077						else
1078						{
1079							mask_v6(mask_value_v6, &data_addr->ipv6_addr_mask[mask_index]);
1080							mask_value_v6 = 0;
1081						}
1082					}
1083
1084					IPACMDBG("ADD IPV6 MASK %d: %08x:%08x:%08x:%08x \n",
1085									 msg_ptr->nl_route_info.metainfo.rtm_dst_len,
1086									 data_addr->ipv6_addr_mask[0],
1087									 data_addr->ipv6_addr_mask[1],
1088									 data_addr->ipv6_addr_mask[2],
1089									 data_addr->ipv6_addr_mask[3]);
1090
1091					data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]);
1092					data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]);
1093					data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]);
1094					data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]);
1095
1096					evt_data.event = IPA_ROUTE_ADD_EVENT;
1097					data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index;
1098					data_addr->iptype = IPA_IP_v6;
1099
1100					IPACMDBG("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv6 addr\n",
1101									 data_addr->if_index);
1102					evt_data.evt_data = data_addr;
1103					IPACM_EvtDispatcher::PostEvt(&evt_data);
1104					/* finish command queue */
1105				}
1106				if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_GATEWAY)
1107				{
1108					IPACM_NL_REPORT_ADDR( "Route ADD ::/0  Next Hop:", msg_ptr->nl_route_info.attr_info.gateway_addr );
1109					IPACMDBG(" metric %d, dev %s\n",
1110									 msg_ptr->nl_route_info.attr_info.priority,
1111									 dev_name);
1112
1113					/* insert to command queue */
1114					data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
1115					if(data_addr == NULL)
1116					{
1117						IPACMERR("unable to allocate memory for event data_addr\n");
1118						return IPACM_FAILURE;
1119					}
1120
1121					IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr);
1122
1123                    data_addr->ipv6_addr[0]=ntohl(data_addr->ipv6_addr[0]);
1124                    data_addr->ipv6_addr[1]=ntohl(data_addr->ipv6_addr[1]);
1125                    data_addr->ipv6_addr[2]=ntohl(data_addr->ipv6_addr[2]);
1126                    data_addr->ipv6_addr[3]=ntohl(data_addr->ipv6_addr[3]);
1127
1128					IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr);
1129
1130					data_addr->ipv6_addr_mask[0]=ntohl(data_addr->ipv6_addr_mask[0]);
1131                    data_addr->ipv6_addr_mask[1]=ntohl(data_addr->ipv6_addr_mask[1]);
1132                    data_addr->ipv6_addr_mask[2]=ntohl(data_addr->ipv6_addr_mask[2]);
1133                    data_addr->ipv6_addr_mask[3]=ntohl(data_addr->ipv6_addr_mask[3]);
1134
1135					evt_data.event = IPA_ROUTE_ADD_EVENT;
1136					data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index;
1137					data_addr->iptype = IPA_IP_v6;
1138
1139					IPACMDBG("posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv6 address\n",
1140									 data_addr->if_index);
1141					evt_data.evt_data = data_addr;
1142					IPACM_EvtDispatcher::PostEvt(&evt_data);
1143					/* finish command queue */
1144				}
1145			}
1146			break;
1147
1148		case RTM_DELROUTE:
1149			if(IPACM_SUCCESS != ipa_nl_decode_rtm_route(buffer, buflen, &(msg_ptr->nl_route_info)))
1150			{
1151				IPACMERR("Failed to decode rtm route message\n");
1152				return IPACM_FAILURE;
1153			}
1154			/* take care of route delete of default route & uniroute */
1155			if((msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) &&
1156				 ((msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) ||
1157				  (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_RA)) &&
1158				 (msg_ptr->nl_route_info.metainfo.rtm_scope == 0) &&
1159				 (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN))
1160			{
1161
1162				if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST)
1163				{
1164					ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index);
1165					if(ret_val != IPACM_SUCCESS)
1166					{
1167						IPACMERR("Error while getting interface name\n");
1168						return IPACM_FAILURE;
1169					}
1170					IPACM_NL_REPORT_ADDR( "route del -host ", msg_ptr->nl_route_info.attr_info.dst_addr);
1171					IPACM_NL_REPORT_ADDR( " gw ", msg_ptr->nl_route_info.attr_info.gateway_addr);
1172					IPACMDBG("dev %s\n", dev_name);
1173
1174					/* insert to command queue */
1175					data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
1176					if(data_addr == NULL)
1177					{
1178						IPACMERR("unable to allocate memory for event data_addr\n");
1179						return IPACM_FAILURE;
1180					}
1181					IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr);
1182					temp = (-1);
1183					if_ipipv4_addr_mask = ntohl(temp);
1184
1185					evt_data.event = IPA_ROUTE_DEL_EVENT;
1186					data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index;
1187					data_addr->iptype = IPA_IP_v4;
1188					data_addr->ipv4_addr = ntohl(if_ipv4_addr);
1189					data_addr->ipv4_addr_mask = ntohl(if_ipipv4_addr_mask);
1190
1191					IPACMDBG_H("Posting event IPA_ROUTE_DEL_EVENT with if index:%d, ipv4 address 0x%x, mask:0x%x\n",
1192									 data_addr->if_index,
1193									 data_addr->ipv4_addr,
1194									 data_addr->ipv4_addr_mask);
1195					evt_data.evt_data = data_addr;
1196					IPACM_EvtDispatcher::PostEvt(&evt_data);
1197					/* finish command queue */
1198				}
1199				else
1200				{
1201					ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index);
1202					if(ret_val != IPACM_SUCCESS)
1203					{
1204						IPACMERR("Error while getting interface name\n");
1205						return IPACM_FAILURE;
1206					}
1207
1208					/* insert to command queue */
1209					data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
1210					if(data_addr == NULL)
1211					{
1212						IPACMERR("unable to allocate memory for event data_addr\n");
1213						return IPACM_FAILURE;
1214					}
1215
1216					if(AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family)
1217					{
1218						if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_PRIORITY)
1219						{
1220							IPACMDBG("ip -6 route del default dev %s metric %d\n",
1221											 dev_name,
1222											 msg_ptr->nl_route_info.attr_info.priority);
1223						}
1224						else
1225						{
1226							IPACMDBG("ip -6 route del default dev %s\n", dev_name);
1227						}
1228						IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr);
1229						data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]);
1230						data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
1231						data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
1232						data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
1233
1234						IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr);
1235						data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]);
1236						data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]);
1237						data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]);
1238						data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]);
1239
1240						IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr);
1241						data_addr->ipv6_addr_gw[0] = ntohl(data_addr->ipv6_addr_gw[0]);
1242						data_addr->ipv6_addr_gw[1] = ntohl(data_addr->ipv6_addr_gw[1]);
1243						data_addr->ipv6_addr_gw[2] = ntohl(data_addr->ipv6_addr_gw[2]);
1244						data_addr->ipv6_addr_gw[3] = ntohl(data_addr->ipv6_addr_gw[3]);
1245						IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_route_info.attr_info.gateway_addr);
1246						data_addr->iptype = IPA_IP_v6;
1247					}
1248					else
1249					{
1250						IPACM_NL_REPORT_ADDR( "route del default gw", msg_ptr->nl_route_info.attr_info.gateway_addr);
1251						IPACMDBG("dev %s\n", dev_name);
1252
1253						IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr);
1254						data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr);
1255
1256						IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr);
1257						data_addr->ipv4_addr_mask = ntohl(data_addr->ipv4_addr_mask);
1258
1259						data_addr->iptype = IPA_IP_v4;
1260					}
1261
1262					evt_data.event = IPA_ROUTE_DEL_EVENT;
1263					data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index;
1264
1265					IPACMDBG_H("Posting IPA_ROUTE_DEL_EVENT with if index:%d\n",
1266									 data_addr->if_index);
1267					evt_data.evt_data = data_addr;
1268					IPACM_EvtDispatcher::PostEvt(&evt_data);
1269					/* finish command queue */
1270				}
1271			}
1272
1273			/* ipv6 routing table */
1274			if((AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) &&
1275				 (msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) &&
1276				 (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_KERNEL) &&
1277				 (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN))
1278			{
1279				IPACMDBG("\n GOT valid v6-RTM_DELROUTE event\n");
1280				ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index);
1281				if(ret_val != IPACM_SUCCESS)
1282				{
1283					IPACMERR("Error while getting interface name");
1284					return IPACM_FAILURE;
1285				}
1286
1287				if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST)
1288				{
1289					IPACM_NL_REPORT_ADDR( "DEL", msg_ptr->nl_route_info.attr_info.dst_addr);
1290					IPACMDBG("/%d, metric %d, dev %s\n",
1291									 msg_ptr->nl_route_info.metainfo.rtm_dst_len,
1292									 msg_ptr->nl_route_info.attr_info.priority,
1293									 dev_name);
1294
1295					/* insert to command queue */
1296					data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
1297					if(data_addr == NULL)
1298					{
1299						IPACMERR("unable to allocate memory for event data_addr\n");
1300						return IPACM_FAILURE;
1301					}
1302
1303					IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr);
1304
1305					data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]);
1306					data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
1307					data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
1308					data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
1309
1310					mask_value_v6 = msg_ptr->nl_route_info.metainfo.rtm_dst_len;
1311					for(mask_index = 0; mask_index < 4; mask_index++)
1312					{
1313						IPACMDBG("%dst %d \n",
1314										 mask_index,
1315										 mask_value_v6);
1316						if(mask_value_v6 >= 32)
1317						{
1318							mask_v6(32, &data_addr->ipv6_addr_mask[mask_index]);
1319							mask_value_v6 -= 32;
1320							IPACMDBG("%dst: %08x \n",
1321											 mask_index,
1322											 data_addr->ipv6_addr_mask[mask_index]);
1323						}
1324						else
1325						{
1326							mask_v6(mask_value_v6, data_addr->ipv6_addr_mask);
1327							mask_value_v6 = 0;
1328							IPACMDBG("%dst: %08x \n",
1329											 mask_index,
1330											 data_addr->ipv6_addr_mask[mask_index]);
1331						}
1332					}
1333
1334					IPACMDBG("DEL IPV6 MASK 0st: %08x ",
1335									 data_addr->ipv6_addr_mask[0]);
1336					IPACMDBG("1st: %08x ",
1337									 data_addr->ipv6_addr_mask[1]);
1338					IPACMDBG("2st: %08x ",
1339									 data_addr->ipv6_addr_mask[2]);
1340					IPACMDBG("3st: %08x \n",
1341									 data_addr->ipv6_addr_mask[3]);
1342
1343					data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]);
1344					data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]);
1345					data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]);
1346					data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]);
1347
1348					evt_data.event = IPA_ROUTE_DEL_EVENT;
1349					data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index;
1350					data_addr->iptype = IPA_IP_v6;
1351
1352					IPACMDBG_H("posting event IPA_ROUTE_DEL_EVENT with if index:%d, ipv4 address\n",
1353									 data_addr->if_index);
1354					evt_data.evt_data = data_addr;
1355					IPACM_EvtDispatcher::PostEvt(&evt_data);
1356					/* finish command queue */
1357				}
1358			}
1359			break;
1360
1361		case RTM_NEWNEIGH:
1362			if(IPACM_SUCCESS != ipa_nl_decode_rtm_neigh(buffer, buflen, &(msg_ptr->nl_neigh_info)))
1363			{
1364				IPACMERR("Failed to decode rtm neighbor message\n");
1365				return IPACM_FAILURE;
1366			}
1367
1368			ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_neigh_info.metainfo.ndm_ifindex);
1369			if(ret_val != IPACM_SUCCESS)
1370			{
1371				IPACMERR("Error while getting interface index\n");
1372				return IPACM_FAILURE;
1373			}
1374			else
1375				{
1376				IPACMDBG("\n GOT RTM_NEWNEIGH event (%s) ip %d\n",dev_name,msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family);
1377			}
1378
1379			/* insert to command queue */
1380		    data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
1381		    if(data_all == NULL)
1382			{
1383		    	IPACMERR("unable to allocate memory for event data_all\n");
1384						return IPACM_FAILURE;
1385			}
1386
1387		    memset(data_all, 0, sizeof(ipacm_event_data_all));
1388		    if(msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET6)
1389		    {
1390				IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr);
1391				IPACM_EVENT_COPY_ADDR_v6( data_all->ipv6_addr, msg_ptr->nl_neigh_info.attr_info.local_addr);
1392
1393				data_all->ipv6_addr[0]=ntohl(data_all->ipv6_addr[0]);
1394				data_all->ipv6_addr[1]=ntohl(data_all->ipv6_addr[1]);
1395				data_all->ipv6_addr[2]=ntohl(data_all->ipv6_addr[2]);
1396				data_all->ipv6_addr[3]=ntohl(data_all->ipv6_addr[3]);
1397				data_all->iptype = IPA_IP_v6;
1398		    }
1399		    else if (msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET)
1400		    {
1401   				IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr);
1402				IPACM_EVENT_COPY_ADDR_v4( data_all->ipv4_addr, msg_ptr->nl_neigh_info.attr_info.local_addr);
1403		    	data_all->ipv4_addr = ntohl(data_all->ipv4_addr);
1404		    	data_all->iptype = IPA_IP_v4;
1405		    }
1406		    else
1407		    {
1408		        data_all->iptype = IPA_IP_v6;
1409		    }
1410
1411		    IPACMDBG("NDA_LLADDR:MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
1412		     (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[0],
1413		     (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[1],
1414		     (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[2],
1415		     (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[3],
1416		     (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[4],
1417		     (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[5]);
1418
1419
1420		    memcpy(data_all->mac_addr,
1421		    			 msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr.sa_data,
1422		    			 sizeof(data_all->mac_addr));
1423			data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex;
1424			/* Add support to replace src-mac as bridge0 mac */
1425			if((msg_ptr->nl_neigh_info.metainfo.ndm_family == AF_BRIDGE) &&
1426				(msg_ptr->nl_neigh_info.metainfo.ndm_state == NUD_PERMANENT))
1427		    {
1428				/* Posting IPA_BRIDGE_LINK_UP_EVENT event */
1429				evt_data.event = IPA_BRIDGE_LINK_UP_EVENT;
1430				IPACMDBG_H("posting IPA_BRIDGE_LINK_UP_EVENT (%s):index:%d \n",
1431                                 dev_name,
1432 		                    data_all->if_index);
1433			}
1434			else
1435		    {
1436				/* Posting new_neigh events for all LAN/WAN clients */
1437				evt_data.event = IPA_NEW_NEIGH_EVENT;
1438				IPACMDBG_H("posting IPA_NEW_NEIGH_EVENT (%s):index:%d ip-family: %d\n",
1439                                 dev_name,
1440 		                    data_all->if_index,
1441		    				 msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family);
1442			}
1443		    evt_data.evt_data = data_all;
1444					IPACM_EvtDispatcher::PostEvt(&evt_data);
1445					/* finish command queue */
1446			break;
1447
1448		case RTM_DELNEIGH:
1449			if(IPACM_SUCCESS != ipa_nl_decode_rtm_neigh(buffer, buflen, &(msg_ptr->nl_neigh_info)))
1450			{
1451				IPACMERR("Failed to decode rtm neighbor message\n");
1452				return IPACM_FAILURE;
1453			}
1454
1455			ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_neigh_info.metainfo.ndm_ifindex);
1456			if(ret_val != IPACM_SUCCESS)
1457			{
1458				IPACMERR("Error while getting interface index\n");
1459				return IPACM_FAILURE;
1460			}
1461			else
1462			{
1463				IPACMDBG("\n GOT RTM_DELNEIGH event (%s) ip %d\n",dev_name,msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family);
1464			}
1465
1466				/* insert to command queue */
1467				data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
1468				if(data_all == NULL)
1469				{
1470					IPACMERR("unable to allocate memory for event data_all\n");
1471					return IPACM_FAILURE;
1472				}
1473
1474		    memset(data_all, 0, sizeof(ipacm_event_data_all));
1475		    if(msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET6)
1476				{
1477					IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr);
1478					IPACM_EVENT_COPY_ADDR_v6( data_all->ipv6_addr, msg_ptr->nl_neigh_info.attr_info.local_addr);
1479
1480					data_all->ipv6_addr[0] = ntohl(data_all->ipv6_addr[0]);
1481					data_all->ipv6_addr[1] = ntohl(data_all->ipv6_addr[1]);
1482					data_all->ipv6_addr[2] = ntohl(data_all->ipv6_addr[2]);
1483					data_all->ipv6_addr[3] = ntohl(data_all->ipv6_addr[3]);
1484					data_all->iptype = IPA_IP_v6;
1485				}
1486		    else if (msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET)
1487				{
1488					IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr);
1489					IPACM_EVENT_COPY_ADDR_v4( data_all->ipv4_addr, msg_ptr->nl_neigh_info.attr_info.local_addr);
1490					data_all->ipv4_addr = ntohl(data_all->ipv4_addr);
1491					data_all->iptype = IPA_IP_v4;
1492				}
1493		    else
1494		    {
1495		        data_all->iptype = IPA_IP_v6;
1496		    }
1497
1498		    IPACMDBG("NDA_LLADDR:MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
1499		     (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[0],
1500		     (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[1],
1501		     (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[2],
1502		     (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[3],
1503		     (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[4],
1504		     (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[5]);
1505
1506				memcpy(data_all->mac_addr,
1507							 msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr.sa_data,
1508							 sizeof(data_all->mac_addr));
1509		    evt_data.event = IPA_DEL_NEIGH_EVENT;
1510				data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex;
1511
1512		    IPACMDBG_H("posting IPA_DEL_NEIGH_EVENT (%s):index:%d ip-family: %d\n",
1513                                 dev_name,
1514 		                    data_all->if_index,
1515		    				 msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family);
1516				evt_data.evt_data = data_all;
1517				IPACM_EvtDispatcher::PostEvt(&evt_data);
1518				/* finish command queue */
1519			break;
1520
1521		default:
1522			IPACMDBG(" ignore NL event %d!!!\n ", nlh->nlmsg_type);
1523			break;
1524
1525		}
1526		nlh = NLMSG_NEXT(nlh, buflen);
1527	}
1528
1529	return IPACM_SUCCESS;
1530}
1531
1532
1533/*  Virtual function registered to receive incoming messages over the NETLINK routing socket*/
1534int ipa_nl_recv_msg(int fd)
1535{
1536	struct msghdr *msghdr = NULL;
1537	struct iovec *iov = NULL;
1538	unsigned int msglen = 0;
1539	ipa_nl_msg_t *nlmsg = NULL;
1540
1541	nlmsg = (ipa_nl_msg_t *)malloc(sizeof(ipa_nl_msg_t));
1542	if(NULL == nlmsg)
1543	{
1544		IPACMERR("Failed alloc of nlmsg \n");
1545		goto error;
1546	}
1547	else
1548	{
1549		if(IPACM_SUCCESS != ipa_nl_recv(fd, &msghdr, &msglen))
1550		{
1551			IPACMERR("Failed to receive nl message \n");
1552			goto error;
1553		}
1554
1555		if(msghdr== NULL)
1556		{
1557			IPACMERR(" failed to get msghdr\n");
1558			goto error;
1559		}
1560
1561		iov = msghdr->msg_iov;
1562
1563		memset(nlmsg, 0, sizeof(ipa_nl_msg_t));
1564		if(IPACM_SUCCESS != ipa_nl_decode_nlmsg((char *)iov->iov_base, msglen, nlmsg))
1565		{
1566			IPACMERR("Failed to decode nl message \n");
1567			goto error;
1568		}
1569		/* Release NetLink message buffer */
1570		if(msghdr)
1571		{
1572			ipa_nl_release_msg(msghdr);
1573		}
1574		if(nlmsg)
1575		{
1576			free(nlmsg);
1577		}
1578	}
1579
1580	return IPACM_SUCCESS;
1581
1582error:
1583	if(msghdr)
1584	{
1585		ipa_nl_release_msg(msghdr);
1586	}
1587	if(nlmsg)
1588	{
1589		free(nlmsg);
1590	}
1591
1592	return IPACM_FAILURE;
1593}
1594
1595/*  get ipa interface name */
1596int ipa_get_if_name
1597(
1598	 char *if_name,
1599	 int if_index
1600	 )
1601{
1602	int fd;
1603	struct ifreq ifr;
1604
1605	if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1606	{
1607		IPACMERR("get interface name socket create failed \n");
1608		return IPACM_FAILURE;
1609	}
1610
1611	memset(&ifr, 0, sizeof(struct ifreq));
1612	ifr.ifr_ifindex = if_index;
1613	IPACMDBG("Interface index %d\n", if_index);
1614
1615	if(ioctl(fd, SIOCGIFNAME, &ifr) < 0)
1616	{
1617		IPACMERR("call_ioctl_on_dev: ioctl failed:\n");
1618		close(fd);
1619		return IPACM_FAILURE;
1620	}
1621
1622	(void)strncpy(if_name, ifr.ifr_name, sizeof(ifr.ifr_name));
1623	IPACMDBG("interface name %s\n", ifr.ifr_name);
1624	close(fd);
1625
1626	return IPACM_SUCCESS;
1627}
1628
1629/* Initialization routine for listener on NetLink sockets interface */
1630int ipa_nl_listener_init
1631(
1632	 unsigned int nl_type,
1633	 unsigned int nl_groups,
1634	 ipa_nl_sk_fd_set_info_t *sk_fdset,
1635	 ipa_sock_thrd_fd_read_f read_f
1636	 )
1637{
1638	ipa_nl_sk_info_t sk_info;
1639	int ret_val;
1640
1641	memset(&sk_info, 0, sizeof(ipa_nl_sk_info_t));
1642	IPACMDBG_H("Entering IPA NL listener init\n");
1643
1644	if(ipa_nl_open_socket(&sk_info, nl_type, nl_groups) == IPACM_SUCCESS)
1645	{
1646		IPACMDBG_H("IPA Open netlink socket succeeds\n");
1647	}
1648	else
1649	{
1650		IPACMERR("Netlink socket open failed\n");
1651		return IPACM_FAILURE;
1652	}
1653
1654	/* Add NETLINK socket to the list of sockets that the listener
1655					 thread should listen on. */
1656
1657	if(ipa_nl_addfd_map(sk_fdset, sk_info.sk_fd, read_f) != IPACM_SUCCESS)
1658	{
1659		IPACMERR("cannot add nl routing sock for reading\n");
1660		close(sk_info.sk_fd);
1661		return IPACM_FAILURE;
1662	}
1663
1664	/* Start the socket listener thread */
1665	ret_val = ipa_nl_sock_listener_start(sk_fdset);
1666
1667	if(ret_val != IPACM_SUCCESS)
1668	{
1669		IPACMERR("Failed to start NL listener\n");
1670	}
1671
1672	return IPACM_SUCCESS;
1673}
1674
1675/* find the newroute subnet mask */
1676int find_mask(int ip_v4_last, int *mask_value)
1677{
1678
1679	switch(ip_v4_last)
1680	{
1681
1682	case 3:
1683		*mask_value = 252;
1684		return IPACM_SUCCESS;
1685		break;
1686
1687	case 7:
1688		*mask_value = 248;
1689		return IPACM_SUCCESS;
1690		break;
1691
1692	case 15:
1693		*mask_value = 240;
1694		return IPACM_SUCCESS;
1695		break;
1696
1697	case 31:
1698		*mask_value = 224;
1699		return IPACM_SUCCESS;
1700		break;
1701
1702	case 63:
1703		*mask_value = 192;
1704		return IPACM_SUCCESS;
1705		break;
1706
1707	case 127:
1708		*mask_value = 128;
1709		return IPACM_SUCCESS;
1710		break;
1711
1712	case 255:
1713		*mask_value = 0;
1714		return IPACM_SUCCESS;
1715		break;
1716
1717	default:
1718		return IPACM_FAILURE;
1719		break;
1720
1721	}
1722}
1723
1724/* map mask value for ipv6 */
1725int mask_v6(int index, uint32_t *mask)
1726{
1727	switch(index)
1728	{
1729
1730	case 0:
1731		*mask = 0x00000000;
1732		return IPACM_SUCCESS;
1733		break;
1734	case 4:
1735		*mask = 0xf0000000;
1736		return IPACM_SUCCESS;
1737		break;
1738	case 8:
1739		*mask = 0xff000000;
1740		return IPACM_SUCCESS;
1741		break;
1742	case 12:
1743		*mask = 0xfff00000;
1744		return IPACM_SUCCESS;
1745		break;
1746	case 16:
1747		*mask = 0xffff0000;
1748		return IPACM_SUCCESS;
1749		break;
1750	case 20:
1751		*mask = 0xfffff000;
1752		return IPACM_SUCCESS;
1753		break;
1754	case 24:
1755		*mask = 0xffffff00;
1756		return IPACM_SUCCESS;
1757		break;
1758	case 28:
1759		*mask = 0xfffffff0;
1760		return IPACM_SUCCESS;
1761		break;
1762	case 32:
1763		*mask = 0xffffffff;
1764		return IPACM_SUCCESS;
1765		break;
1766	default:
1767		return IPACM_FAILURE;
1768		break;
1769
1770	}
1771}
1772
1773
1774