You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1773 lines
56 KiB
1773 lines
56 KiB
/* |
|
Copyright (c) 2013, The Linux Foundation. All rights reserved. |
|
|
|
Redistribution and use in source and binary forms, with or without |
|
modification, are permitted provided that the following conditions are |
|
met: |
|
* Redistributions of source code must retain the above copyright |
|
notice, this list of conditions and the following disclaimer. |
|
* Redistributions in binary form must reproduce the above |
|
copyright notice, this list of conditions and the following |
|
disclaimer in the documentation and/or other materials provided |
|
with the distribution. |
|
* Neither the name of The Linux Foundation nor the names of its |
|
contributors may be used to endorse or promote products derived |
|
from this software without specific prior written permission. |
|
|
|
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
|
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
|
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
|
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
*/ |
|
/*! |
|
@file |
|
IPACM_Netlink.cpp |
|
|
|
@brief |
|
This file implements the IPAM Netlink Socket Parer functionality. |
|
|
|
@Author |
|
Skylar Chang |
|
|
|
*/ |
|
#include <string.h> |
|
#include <unistd.h> |
|
#include <sys/ioctl.h> |
|
#include <netinet/in.h> |
|
#include "IPACM_CmdQueue.h" |
|
#include "IPACM_Defs.h" |
|
#include "IPACM_Netlink.h" |
|
#include "IPACM_EvtDispatcher.h" |
|
#include "IPACM_Log.h" |
|
|
|
int ipa_get_if_name(char *if_name, int if_index); |
|
int find_mask(int ip_v4_last, int *mask_value); |
|
|
|
#ifdef FEATURE_IPA_ANDROID |
|
|
|
#define IPACM_NL_COPY_ADDR( event_info, element ) \ |
|
memcpy( &event_info->attr_info.element.__data, \ |
|
RTA_DATA(rtah), \ |
|
sizeof(event_info->attr_info.element.__data) ); |
|
|
|
#define IPACM_EVENT_COPY_ADDR_v6( event_data, element) \ |
|
memcpy( event_data, element.__data, sizeof(event_data)); |
|
|
|
#define IPACM_EVENT_COPY_ADDR_v4( event_data, element) \ |
|
memcpy( &event_data, element.__data, sizeof(event_data)); |
|
|
|
#define IPACM_NL_REPORT_ADDR( prefix, addr ) \ |
|
if( AF_INET6 == (addr).ss_family ) { \ |
|
IPACM_LOG_IPV6_ADDR( prefix, addr.__data); \ |
|
} else { \ |
|
IPACM_LOG_IPV4_ADDR( prefix, (*(unsigned int*)&(addr).__data) ); \ |
|
} |
|
|
|
#else/* defined(FEATURE_IPA_ANDROID) */ |
|
|
|
#define IPACM_NL_COPY_ADDR( event_info, element ) \ |
|
memcpy( &event_info->attr_info.element.__ss_padding, \ |
|
RTA_DATA(rtah), \ |
|
sizeof(event_info->attr_info.element.__ss_padding) ); |
|
|
|
#define IPACM_EVENT_COPY_ADDR_v6( event_data, element) \ |
|
memcpy( event_data, element.__ss_padding, sizeof(event_data)); |
|
|
|
#define IPACM_EVENT_COPY_ADDR_v4( event_data, element) \ |
|
memcpy( &event_data, element.__ss_padding, sizeof(event_data)); |
|
|
|
#define IPACM_NL_REPORT_ADDR( prefix, addr ) \ |
|
if( AF_INET6 == (addr).ss_family ) { \ |
|
IPACM_LOG_IPV6_ADDR( prefix, addr.__ss_padding); \ |
|
} else { \ |
|
IPACM_LOG_IPV4_ADDR( prefix, (*(unsigned int*)&(addr).__ss_padding) ); \ |
|
} |
|
#endif /* defined(FEATURE_IPA_ANDROID)*/ |
|
|
|
#define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) |
|
#define IPACM_LOG_IPV6_ADDR(prefix, ip_addr) \ |
|
IPACMDBG_H(prefix); \ |
|
IPACMDBG_H(" IPV6 Address %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", \ |
|
(int)ip_addr[0], (int)ip_addr[1], \ |
|
(int)ip_addr[2], (int)ip_addr[3], \ |
|
(int)ip_addr[4], (int)ip_addr[5], \ |
|
(int)ip_addr[6], (int)ip_addr[7], \ |
|
(int)ip_addr[8], (int)ip_addr[9], \ |
|
(int)ip_addr[10], (int)ip_addr[11], \ |
|
(int)ip_addr[12], (int)ip_addr[13], \ |
|
(int)ip_addr[14], (int)ip_addr[15]); |
|
|
|
#define IPACM_LOG_IPV4_ADDR(prefix, ip_addr) \ |
|
IPACMDBG_H(prefix); \ |
|
IPACMDBG_H(" IPV4 Address %d.%d.%d.%d\n", \ |
|
(unsigned char)(ip_addr), \ |
|
(unsigned char)(ip_addr >> 8), \ |
|
(unsigned char)(ip_addr >> 16) , \ |
|
(unsigned char)(ip_addr >> 24)); |
|
|
|
/* Opens a netlink socket*/ |
|
static int ipa_nl_open_socket |
|
( |
|
ipa_nl_sk_info_t *sk_info, |
|
int protocol, |
|
unsigned int grps |
|
) |
|
{ |
|
int *p_sk_fd; |
|
int buf_size = 6669999, sendbuff=0, res; |
|
struct sockaddr_nl *p_sk_addr_loc; |
|
socklen_t optlen; |
|
|
|
p_sk_fd = &(sk_info->sk_fd); |
|
p_sk_addr_loc = &(sk_info->sk_addr_loc); |
|
|
|
/* Open netlink socket for specified protocol */ |
|
if((*p_sk_fd = socket(AF_NETLINK, SOCK_RAW, protocol)) < 0) |
|
{ |
|
IPACMERR("cannot open netlink socket\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
optlen = sizeof(sendbuff); |
|
res = getsockopt(*p_sk_fd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen); |
|
|
|
if(res == -1) { |
|
IPACMDBG("Error getsockopt one"); |
|
} else { |
|
IPACMDBG("orignal send buffer size = %d\n", sendbuff); |
|
} |
|
IPACMDBG("sets the send buffer to %d\n", buf_size); |
|
if (setsockopt(*p_sk_fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(int)) == -1) { |
|
IPACMERR("Error setting socket opts\n"); |
|
} |
|
|
|
/* Initialize socket addresses to null */ |
|
memset(p_sk_addr_loc, 0, sizeof(struct sockaddr_nl)); |
|
|
|
/* Populate local socket address using specified groups */ |
|
p_sk_addr_loc->nl_family = AF_NETLINK; |
|
p_sk_addr_loc->nl_pid = getpid(); |
|
p_sk_addr_loc->nl_groups = grps; |
|
|
|
/* Bind socket to the local address, i.e. specified groups. This ensures |
|
that multicast messages for these groups are delivered over this |
|
socket. */ |
|
|
|
if(bind(*p_sk_fd, |
|
(struct sockaddr *)p_sk_addr_loc, |
|
sizeof(struct sockaddr_nl)) < 0) |
|
{ |
|
IPACMERR("Socket bind failed\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
return IPACM_SUCCESS; |
|
} |
|
|
|
/* Add fd to fdmap array and store read handler function ptr (up to MAX_NUM_OF_FD).*/ |
|
static int ipa_nl_addfd_map |
|
( |
|
ipa_nl_sk_fd_set_info_t *info, |
|
int fd, |
|
ipa_sock_thrd_fd_read_f read_f |
|
) |
|
{ |
|
if(info->num_fd < MAX_NUM_OF_FD) |
|
{ |
|
FD_SET(fd, &info->fdset); |
|
|
|
/* Add fd to fdmap array and store read handler function ptr */ |
|
info->sk_fds[info->num_fd].sk_fd = fd; |
|
info->sk_fds[info->num_fd].read_func = read_f; |
|
|
|
/* Increment number of fds stored in fdmap */ |
|
info->num_fd++; |
|
if(info->max_fd < fd) |
|
info->max_fd = fd; |
|
} |
|
else |
|
{ |
|
return IPACM_FAILURE; |
|
} |
|
|
|
return IPACM_SUCCESS; |
|
} |
|
|
|
/* start socket listener */ |
|
static int ipa_nl_sock_listener_start |
|
( |
|
ipa_nl_sk_fd_set_info_t *sk_fd_set |
|
) |
|
{ |
|
int i, ret; |
|
|
|
while(true) |
|
{ |
|
for(i = 0; i < sk_fd_set->num_fd; i++ ) |
|
{ |
|
FD_SET(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset)); |
|
} |
|
|
|
if((ret = select(sk_fd_set->max_fd + 1, &(sk_fd_set->fdset), NULL, NULL, NULL)) < 0) |
|
{ |
|
IPACMERR("ipa_nl select failed\n"); |
|
} |
|
else |
|
{ |
|
for(i = 0; i < sk_fd_set->num_fd; i++) |
|
{ |
|
|
|
if(FD_ISSET(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset))) |
|
{ |
|
|
|
if(sk_fd_set->sk_fds[i].read_func) |
|
{ |
|
if(IPACM_SUCCESS != ((sk_fd_set->sk_fds[i].read_func)(sk_fd_set->sk_fds[i].sk_fd))) |
|
{ |
|
IPACMERR("Error on read callback[%d] fd=%d\n", |
|
i, |
|
sk_fd_set->sk_fds[i].sk_fd); |
|
} |
|
FD_CLR(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset)); |
|
} |
|
else |
|
{ |
|
IPACMERR("No read function\n"); |
|
} |
|
} |
|
|
|
} /* end of for loop*/ |
|
} /* end of else */ |
|
} /* end of while */ |
|
|
|
return IPACM_SUCCESS; |
|
} |
|
|
|
/* allocate memory for ipa_nl__msg */ |
|
static struct msghdr* ipa_nl_alloc_msg |
|
( |
|
uint32_t msglen |
|
) |
|
{ |
|
unsigned char *buf = NULL; |
|
struct sockaddr_nl *nladdr = NULL; |
|
struct iovec *iov = NULL; |
|
struct msghdr *msgh = NULL; |
|
|
|
if(IPA_NL_MSG_MAX_LEN < msglen) |
|
{ |
|
IPACMERR("Netlink message exceeds maximum length\n"); |
|
return NULL; |
|
} |
|
|
|
msgh = (struct msghdr *)malloc(sizeof(struct msghdr)); |
|
if(msgh == NULL) |
|
{ |
|
IPACMERR("Failed malloc for msghdr\n"); |
|
return NULL; |
|
} |
|
|
|
nladdr = (struct sockaddr_nl *)malloc(sizeof(struct sockaddr_nl)); |
|
if(nladdr == NULL) |
|
{ |
|
IPACMERR("Failed malloc for sockaddr\n"); |
|
free(msgh); |
|
return NULL; |
|
} |
|
|
|
iov = (struct iovec *)malloc(sizeof(struct iovec)); |
|
if(iov == NULL) |
|
{ |
|
PERROR("Failed malloc for iovec"); |
|
free(nladdr); |
|
free(msgh); |
|
return NULL; |
|
} |
|
|
|
buf = (unsigned char *)malloc(msglen); |
|
if(buf == NULL) |
|
{ |
|
IPACMERR("Failed malloc for mglen\n"); |
|
free(iov); |
|
free(nladdr); |
|
free(msgh); |
|
return NULL; |
|
} |
|
|
|
memset(nladdr, 0, sizeof(struct sockaddr_nl)); |
|
nladdr->nl_family = AF_NETLINK; |
|
|
|
memset(msgh, 0x0, sizeof(struct msghdr)); |
|
msgh->msg_name = nladdr; |
|
msgh->msg_namelen = sizeof(struct sockaddr_nl); |
|
msgh->msg_iov = iov; |
|
msgh->msg_iovlen = 1; |
|
|
|
memset(iov, 0x0, sizeof(struct iovec)); |
|
iov->iov_base = buf; |
|
iov->iov_len = msglen; |
|
|
|
return msgh; |
|
} |
|
|
|
/* release IPA message */ |
|
static void ipa_nl_release_msg |
|
( |
|
struct msghdr *msgh |
|
) |
|
{ |
|
unsigned char *buf = NULL; |
|
struct sockaddr_nl *nladdr = NULL; |
|
struct iovec *iov = NULL; |
|
|
|
if(NULL == msgh) |
|
{ |
|
return; |
|
} |
|
|
|
nladdr = (struct sockaddr_nl *)msgh->msg_name; |
|
iov = msgh->msg_iov; |
|
if(msgh->msg_iov) |
|
{ |
|
buf = (unsigned char *)msgh->msg_iov->iov_base; |
|
} |
|
|
|
if(buf) |
|
{ |
|
free(buf); |
|
} |
|
if(iov) |
|
{ |
|
free(iov); |
|
} |
|
if(nladdr) |
|
{ |
|
free(nladdr); |
|
} |
|
if(msgh) |
|
{ |
|
free(msgh); |
|
} |
|
return; |
|
} |
|
|
|
/* receive and process nl message */ |
|
static int ipa_nl_recv |
|
( |
|
int fd, |
|
struct msghdr **msg_pptr, |
|
unsigned int *msglen_ptr |
|
) |
|
{ |
|
struct msghdr *msgh = NULL; |
|
int rmsgl; |
|
|
|
msgh = ipa_nl_alloc_msg(IPA_NL_MSG_MAX_LEN); |
|
if(NULL == msgh) |
|
{ |
|
IPACMERR("Failed to allocate NL message\n"); |
|
goto error; |
|
} |
|
|
|
|
|
/* Receive message over the socket */ |
|
rmsgl = recvmsg(fd, msgh, 0); |
|
|
|
/* Verify that something was read */ |
|
if(rmsgl <= 0) |
|
{ |
|
PERROR("NL recv error"); |
|
goto error; |
|
} |
|
|
|
/* Verify that NL address length in the received message is expected value */ |
|
if(sizeof(struct sockaddr_nl) != msgh->msg_namelen) |
|
{ |
|
IPACMERR("rcvd msg with namelen != sizeof sockaddr_nl\n"); |
|
goto error; |
|
} |
|
|
|
/* Verify that message was not truncated. This should not occur */ |
|
if(msgh->msg_flags & MSG_TRUNC) |
|
{ |
|
IPACMERR("Rcvd msg truncated!\n"); |
|
goto error; |
|
} |
|
|
|
*msg_pptr = msgh; |
|
*msglen_ptr = rmsgl; |
|
|
|
return IPACM_SUCCESS; |
|
|
|
/* An error occurred while receiving the message. Free all memory before |
|
returning. */ |
|
error: |
|
ipa_nl_release_msg(msgh); |
|
*msg_pptr = NULL; |
|
*msglen_ptr = 0; |
|
|
|
return IPACM_FAILURE; |
|
} |
|
|
|
/* decode the rtm netlink message */ |
|
static int ipa_nl_decode_rtm_link |
|
( |
|
const char *buffer, |
|
unsigned int buflen, |
|
ipa_nl_link_info_t *link_info |
|
) |
|
{ |
|
struct rtattr; |
|
/* NL message header */ |
|
struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; |
|
|
|
/* Extract the header data */ |
|
link_info->metainfo = *(struct ifinfomsg *)NLMSG_DATA(nlh); |
|
buflen -= sizeof(struct nlmsghdr); |
|
|
|
return IPACM_SUCCESS; |
|
} |
|
|
|
/* Decode kernel address message parameters from Netlink attribute TLVs. */ |
|
static int ipa_nl_decode_rtm_addr |
|
( |
|
const char *buffer, |
|
unsigned int buflen, |
|
ipa_nl_addr_info_t *addr_info |
|
) |
|
{ |
|
struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; /* NL message header */ |
|
struct rtattr *rtah = NULL; |
|
|
|
/* Extract the header data */ |
|
addr_info->metainfo = *((struct ifaddrmsg *)NLMSG_DATA(nlh)); |
|
buflen -= sizeof(struct nlmsghdr); |
|
|
|
/* Extract the available attributes */ |
|
addr_info->attr_info.param_mask = IPA_NLA_PARAM_NONE; |
|
|
|
rtah = IFA_RTA(NLMSG_DATA(nlh)); |
|
|
|
while(RTA_OK(rtah, buflen)) |
|
{ |
|
switch(rtah->rta_type) |
|
{ |
|
|
|
case IFA_ADDRESS: |
|
addr_info->attr_info.prefix_addr.ss_family = addr_info->metainfo.ifa_family; |
|
IPACM_NL_COPY_ADDR( addr_info, prefix_addr ); |
|
addr_info->attr_info.param_mask |= IPA_NLA_PARAM_PREFIXADDR; |
|
break; |
|
default: |
|
break; |
|
|
|
} |
|
/* Advance to next attribute */ |
|
rtah = RTA_NEXT(rtah, buflen); |
|
} |
|
|
|
return IPACM_SUCCESS; |
|
} |
|
|
|
/* Decode kernel neighbor message parameters from Netlink attribute TLVs. */ |
|
static int ipa_nl_decode_rtm_neigh |
|
( |
|
const char *buffer, |
|
unsigned int buflen, |
|
ipa_nl_neigh_info_t *neigh_info |
|
) |
|
{ |
|
struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; /* NL message header */ |
|
struct rtattr *rtah = NULL; |
|
|
|
/* Extract the header data */ |
|
neigh_info->metainfo = *((struct ndmsg *)NLMSG_DATA(nlh)); |
|
buflen -= sizeof(struct nlmsghdr); |
|
|
|
/* Extract the available attributes */ |
|
neigh_info->attr_info.param_mask = IPA_NLA_PARAM_NONE; |
|
|
|
rtah = NDA_RTA(NLMSG_DATA(nlh)); |
|
|
|
while(RTA_OK(rtah, buflen)) |
|
{ |
|
switch(rtah->rta_type) |
|
{ |
|
|
|
case NDA_DST: |
|
neigh_info->attr_info.local_addr.ss_family = neigh_info->metainfo.ndm_family; |
|
IPACM_NL_COPY_ADDR( neigh_info, local_addr ); |
|
break; |
|
|
|
case NDA_LLADDR: |
|
memcpy(neigh_info->attr_info.lladdr_hwaddr.sa_data, |
|
RTA_DATA(rtah), |
|
sizeof(neigh_info->attr_info.lladdr_hwaddr.sa_data)); |
|
break; |
|
|
|
default: |
|
break; |
|
|
|
} |
|
|
|
/* Advance to next attribute */ |
|
rtah = RTA_NEXT(rtah, buflen); |
|
} |
|
|
|
return IPACM_SUCCESS; |
|
} |
|
|
|
/* Decode kernel route message parameters from Netlink attribute TLVs. */ |
|
static int ipa_nl_decode_rtm_route |
|
( |
|
const char *buffer, |
|
unsigned int buflen, |
|
ipa_nl_route_info_t *route_info |
|
) |
|
{ |
|
struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; /* NL message header */ |
|
struct rtattr *rtah = NULL; |
|
|
|
/* Extract the header data */ |
|
route_info->metainfo = *((struct rtmsg *)NLMSG_DATA(nlh)); |
|
buflen -= sizeof(struct nlmsghdr); |
|
|
|
route_info->attr_info.param_mask = IPA_RTA_PARAM_NONE; |
|
rtah = RTM_RTA(NLMSG_DATA(nlh)); |
|
|
|
while(RTA_OK(rtah, buflen)) |
|
{ |
|
switch(rtah->rta_type) |
|
{ |
|
|
|
case RTA_DST: |
|
route_info->attr_info.dst_addr.ss_family = route_info->metainfo.rtm_family; |
|
IPACM_NL_COPY_ADDR( route_info, dst_addr ); |
|
route_info->attr_info.param_mask |= IPA_RTA_PARAM_DST; |
|
break; |
|
|
|
case RTA_SRC: |
|
route_info->attr_info.src_addr.ss_family = route_info->metainfo.rtm_family; |
|
IPACM_NL_COPY_ADDR( route_info, src_addr ); |
|
route_info->attr_info.param_mask |= IPA_RTA_PARAM_SRC; |
|
break; |
|
|
|
case RTA_GATEWAY: |
|
route_info->attr_info.gateway_addr.ss_family = route_info->metainfo.rtm_family; |
|
IPACM_NL_COPY_ADDR( route_info, gateway_addr ); |
|
route_info->attr_info.param_mask |= IPA_RTA_PARAM_GATEWAY; |
|
break; |
|
|
|
case RTA_IIF: |
|
memcpy(&route_info->attr_info.iif_index, |
|
RTA_DATA(rtah), |
|
sizeof(route_info->attr_info.iif_index)); |
|
route_info->attr_info.param_mask |= IPA_RTA_PARAM_IIF; |
|
break; |
|
|
|
case RTA_OIF: |
|
memcpy(&route_info->attr_info.oif_index, |
|
RTA_DATA(rtah), |
|
sizeof(route_info->attr_info.oif_index)); |
|
route_info->attr_info.param_mask |= IPA_RTA_PARAM_OIF; |
|
break; |
|
|
|
case RTA_PRIORITY: |
|
memcpy(&route_info->attr_info.priority, |
|
RTA_DATA(rtah), |
|
sizeof(route_info->attr_info.priority)); |
|
route_info->attr_info.param_mask |= IPA_RTA_PARAM_PRIORITY; |
|
break; |
|
|
|
default: |
|
break; |
|
|
|
} |
|
|
|
/* Advance to next attribute */ |
|
rtah = RTA_NEXT(rtah, buflen); |
|
} |
|
|
|
return IPACM_SUCCESS; |
|
} |
|
|
|
/* decode the ipa nl-message */ |
|
static int ipa_nl_decode_nlmsg |
|
( |
|
const char *buffer, |
|
unsigned int buflen, |
|
ipa_nl_msg_t *msg_ptr |
|
) |
|
{ |
|
char dev_name[IF_NAME_LEN]={0}; |
|
int ret_val, mask_index, mask_value_v6; |
|
struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; |
|
|
|
uint32_t if_ipv4_addr =0, if_ipipv4_addr_mask =0, temp =0, if_ipv4_addr_gw =0; |
|
|
|
ipacm_cmd_q_data evt_data; |
|
ipacm_event_data_all *data_all; |
|
ipacm_event_data_fid *data_fid; |
|
ipacm_event_data_addr *data_addr; |
|
|
|
|
|
while(NLMSG_OK(nlh, buflen)) |
|
{ |
|
memset(dev_name,0,IF_NAME_LEN); |
|
IPACMDBG("Received msg:%d from netlink\n", nlh->nlmsg_type) |
|
switch(nlh->nlmsg_type) |
|
{ |
|
case RTM_NEWLINK: |
|
msg_ptr->type = nlh->nlmsg_type; |
|
msg_ptr->link_event = true; |
|
if(IPACM_SUCCESS != ipa_nl_decode_rtm_link(buffer, buflen, &(msg_ptr->nl_link_info))) |
|
{ |
|
IPACMERR("Failed to decode rtm link message\n"); |
|
return IPACM_FAILURE; |
|
} |
|
else |
|
{ |
|
IPACMDBG("Got RTM_NEWLINK with below values\n"); |
|
IPACMDBG("RTM_NEWLINK, ifi_change:%d\n", msg_ptr->nl_link_info.metainfo.ifi_change); |
|
IPACMDBG("RTM_NEWLINK, ifi_flags:%d\n", msg_ptr->nl_link_info.metainfo.ifi_flags); |
|
IPACMDBG("RTM_NEWLINK, ifi_index:%d\n", msg_ptr->nl_link_info.metainfo.ifi_index); |
|
IPACMDBG("RTM_NEWLINK, family:%d\n", msg_ptr->nl_link_info.metainfo.ifi_family); |
|
/* RTM_NEWLINK event with AF_BRIDGE family should be ignored in Android |
|
but this should be processed in case of MDM for Ehernet interface. |
|
*/ |
|
#ifdef FEATURE_IPA_ANDROID |
|
if (msg_ptr->nl_link_info.metainfo.ifi_family == AF_BRIDGE) |
|
{ |
|
IPACMERR(" ignore this RTM_NEWLINK msg \n"); |
|
return IPACM_SUCCESS; |
|
} |
|
#endif |
|
if(IFF_UP & msg_ptr->nl_link_info.metainfo.ifi_change) |
|
{ |
|
IPACMDBG("GOT useful newlink event\n"); |
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface name\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); |
|
if(data_fid == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_fid\n"); |
|
return IPACM_FAILURE; |
|
} |
|
data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index; |
|
|
|
if(msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_UP) |
|
{ |
|
IPACMDBG_H("Interface %s bring up with IP-family: %d \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_family); |
|
/* post link up to command queue */ |
|
evt_data.event = IPA_LINK_UP_EVENT; |
|
IPACMDBG_H("Posting IPA_LINK_UP_EVENT with if index: %d\n", |
|
msg_ptr->nl_link_info.metainfo.ifi_index); |
|
} |
|
else |
|
{ |
|
IPACMDBG_H("Interface %s bring down with IP-family: %d \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_family); |
|
/* post link down to command queue */ |
|
evt_data.event = IPA_LINK_DOWN_EVENT; |
|
IPACMDBG_H("Posting IPA_LINK_DOWN_EVENT with if index: %d\n", |
|
data_fid->if_index); |
|
} |
|
evt_data.evt_data = data_fid; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
} |
|
|
|
/* Add IPACM support for ECM plug-in/plug_out */ |
|
/*-------------------------------------------------------------------------- |
|
Check if the interface is running.If its a RTM_NEWLINK and the interface |
|
is running then it means that its a link up event |
|
---------------------------------------------------------------------------*/ |
|
if((msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_RUNNING) && |
|
(msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_LOWER_UP)) |
|
{ |
|
|
|
data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); |
|
if(data_fid == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_fid\n"); |
|
return IPACM_FAILURE; |
|
} |
|
data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index; |
|
|
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface name\n"); |
|
return IPACM_FAILURE; |
|
} |
|
IPACMDBG("Got a usb link_up event (Interface %s, %d) \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); |
|
|
|
/*-------------------------------------------------------------------------- |
|
Post LAN iface (ECM) link up event |
|
---------------------------------------------------------------------------*/ |
|
evt_data.event = IPA_USB_LINK_UP_EVENT; |
|
evt_data.evt_data = data_fid; |
|
IPACMDBG_H("Posting usb IPA_LINK_UP_EVENT with if index: %d\n", |
|
data_fid->if_index); |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
} |
|
else if (!(msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_LOWER_UP)) |
|
{ |
|
data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); |
|
if(data_fid == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_fid\n"); |
|
return IPACM_FAILURE; |
|
} |
|
data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index; |
|
|
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface name\n"); |
|
return IPACM_FAILURE; |
|
} |
|
IPACMDBG_H("Got a usb link_down event (Interface %s) \n", dev_name); |
|
|
|
/*-------------------------------------------------------------------------- |
|
Post LAN iface (ECM) link down event |
|
---------------------------------------------------------------------------*/ |
|
evt_data.event = IPA_LINK_DOWN_EVENT; |
|
evt_data.evt_data = data_fid; |
|
IPACMDBG_H("Posting usb IPA_LINK_DOWN_EVENT with if index: %d\n", |
|
data_fid->if_index); |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
} |
|
} |
|
break; |
|
|
|
case RTM_DELLINK: |
|
IPACMDBG("\n GOT dellink event\n"); |
|
msg_ptr->type = nlh->nlmsg_type; |
|
msg_ptr->link_event = true; |
|
IPACMDBG("entering rtm decode\n"); |
|
if(IPACM_SUCCESS != ipa_nl_decode_rtm_link(buffer, buflen, &(msg_ptr->nl_link_info))) |
|
{ |
|
IPACMERR("Failed to decode rtm link message\n"); |
|
return IPACM_FAILURE; |
|
} |
|
else |
|
{ |
|
IPACMDBG("Got RTM_DELLINK with below values\n"); |
|
IPACMDBG("RTM_DELLINK, ifi_change:%d\n", msg_ptr->nl_link_info.metainfo.ifi_change); |
|
IPACMDBG("RTM_DELLINK, ifi_flags:%d\n", msg_ptr->nl_link_info.metainfo.ifi_flags); |
|
IPACMDBG("RTM_DELLINK, ifi_index:%d\n", msg_ptr->nl_link_info.metainfo.ifi_index); |
|
IPACMDBG("RTM_DELLINK, family:%d\n", msg_ptr->nl_link_info.metainfo.ifi_family); |
|
/* RTM_NEWLINK event with AF_BRIDGE family should be ignored in Android |
|
but this should be processed in case of MDM for Ehernet interface. |
|
*/ |
|
#ifdef FEATURE_IPA_ANDROID |
|
if (msg_ptr->nl_link_info.metainfo.ifi_family == AF_BRIDGE) |
|
{ |
|
IPACMERR(" ignore this RTM_DELLINK msg \n"); |
|
return IPACM_SUCCESS; |
|
} |
|
#endif |
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface name\n"); |
|
return IPACM_FAILURE; |
|
} |
|
IPACMDBG("Interface %s bring down \n", dev_name); |
|
|
|
/* post link down to command queue */ |
|
evt_data.event = IPA_LINK_DOWN_EVENT; |
|
data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); |
|
if(data_fid == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_fid\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index; |
|
|
|
IPACMDBG_H("posting IPA_LINK_DOWN_EVENT with if idnex:%d\n", |
|
data_fid->if_index); |
|
evt_data.evt_data = data_fid; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
/* finish command queue */ |
|
} |
|
break; |
|
|
|
case RTM_NEWADDR: |
|
IPACMDBG("\n GOT RTM_NEWADDR event\n"); |
|
if(IPACM_SUCCESS != ipa_nl_decode_rtm_addr(buffer, buflen, &(msg_ptr->nl_addr_info))) |
|
{ |
|
IPACMERR("Failed to decode rtm addr message\n"); |
|
return IPACM_FAILURE; |
|
} |
|
else |
|
{ |
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_addr_info.metainfo.ifa_index); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface name\n"); |
|
} |
|
IPACMDBG("Interface %s \n", dev_name); |
|
|
|
data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); |
|
if(data_addr == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_addr\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
if(AF_INET6 == msg_ptr->nl_addr_info.attr_info.prefix_addr.ss_family) |
|
{ |
|
data_addr->iptype = IPA_IP_v6; |
|
IPACM_NL_REPORT_ADDR( "IFA_ADDRESS:", msg_ptr->nl_addr_info.attr_info.prefix_addr ); |
|
IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_addr_info.attr_info.prefix_addr); |
|
data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]); |
|
data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); |
|
data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); |
|
data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); |
|
} |
|
else |
|
{ |
|
data_addr->iptype = IPA_IP_v4; |
|
IPACM_NL_REPORT_ADDR( "IFA_ADDRESS:", msg_ptr->nl_addr_info.attr_info.prefix_addr ); |
|
IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr, msg_ptr->nl_addr_info.attr_info.prefix_addr); |
|
data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr); |
|
|
|
} |
|
|
|
evt_data.event = IPA_ADDR_ADD_EVENT; |
|
data_addr->if_index = msg_ptr->nl_addr_info.metainfo.ifa_index; |
|
if(AF_INET6 == msg_ptr->nl_addr_info.attr_info.prefix_addr.ss_family) |
|
{ |
|
IPACMDBG("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv6 addr:0x%x:%x:%x:%x\n", |
|
data_addr->if_index, |
|
data_addr->ipv6_addr[0], |
|
data_addr->ipv6_addr[1], |
|
data_addr->ipv6_addr[2], |
|
data_addr->ipv6_addr[3]); |
|
} |
|
else |
|
{ |
|
IPACMDBG("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv4 addr:0x%x\n", |
|
data_addr->if_index, |
|
data_addr->ipv4_addr); |
|
} |
|
evt_data.evt_data = data_addr; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
} |
|
break; |
|
|
|
case RTM_NEWROUTE: |
|
|
|
if(IPACM_SUCCESS != ipa_nl_decode_rtm_route(buffer, buflen, &(msg_ptr->nl_route_info))) |
|
{ |
|
IPACMERR("Failed to decode rtm route message\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
IPACMDBG("In case RTM_NEWROUTE\n"); |
|
IPACMDBG("rtm_type: %d\n", msg_ptr->nl_route_info.metainfo.rtm_type); |
|
IPACMDBG("protocol: %d\n", msg_ptr->nl_route_info.metainfo.rtm_protocol); |
|
IPACMDBG("rtm_scope: %d\n", msg_ptr->nl_route_info.metainfo.rtm_scope); |
|
IPACMDBG("rtm_table: %d\n", msg_ptr->nl_route_info.metainfo.rtm_table); |
|
IPACMDBG("rtm_family: %d\n", msg_ptr->nl_route_info.metainfo.rtm_family); |
|
IPACMDBG("param_mask: 0x%x\n", msg_ptr->nl_route_info.attr_info.param_mask); |
|
|
|
/* take care of route add default route & uniroute */ |
|
if((msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) && |
|
((msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) || |
|
(msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_RA)) && |
|
(msg_ptr->nl_route_info.metainfo.rtm_scope == RT_SCOPE_UNIVERSE) && |
|
(msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) |
|
{ |
|
IPACMDBG("\n GOT RTM_NEWROUTE event\n"); |
|
|
|
if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST) |
|
{ |
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface name\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
IPACM_NL_REPORT_ADDR( "route add -host", msg_ptr->nl_route_info.attr_info.dst_addr ); |
|
IPACM_NL_REPORT_ADDR( "gw", msg_ptr->nl_route_info.attr_info.gateway_addr ); |
|
IPACMDBG("dev %s\n",dev_name ); |
|
/* insert to command queue */ |
|
IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
temp = (-1); |
|
|
|
evt_data.event = IPA_ROUTE_ADD_EVENT; |
|
data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); |
|
if(data_addr == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_addr\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; |
|
data_addr->iptype = IPA_IP_v4; |
|
data_addr->ipv4_addr = ntohl(if_ipv4_addr); |
|
data_addr->ipv4_addr_mask = ntohl(if_ipipv4_addr_mask); |
|
|
|
IPACMDBG("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv4 address 0x%x, mask:0x%x\n", |
|
data_addr->if_index, |
|
data_addr->ipv4_addr, |
|
data_addr->ipv4_addr_mask); |
|
evt_data.evt_data = data_addr; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
/* finish command queue */ |
|
|
|
} |
|
else |
|
{ |
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface name\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
if(AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) |
|
{ |
|
/* insert to command queue */ |
|
data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); |
|
if(data_addr == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_addr\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_PRIORITY) |
|
{ |
|
IPACMDBG_H("ip -6 route add default dev %s metric %d\n", |
|
dev_name, |
|
msg_ptr->nl_route_info.attr_info.priority); |
|
} |
|
else |
|
{ |
|
IPACMDBG_H("ip -6 route add default dev %s\n", dev_name); |
|
} |
|
|
|
IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]); |
|
data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); |
|
data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); |
|
data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); |
|
|
|
IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]); |
|
data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]); |
|
data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]); |
|
data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]); |
|
|
|
IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr); |
|
data_addr->ipv6_addr_gw[0] = ntohl(data_addr->ipv6_addr_gw[0]); |
|
data_addr->ipv6_addr_gw[1] = ntohl(data_addr->ipv6_addr_gw[1]); |
|
data_addr->ipv6_addr_gw[2] = ntohl(data_addr->ipv6_addr_gw[2]); |
|
data_addr->ipv6_addr_gw[3] = ntohl(data_addr->ipv6_addr_gw[3]); |
|
IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_route_info.attr_info.gateway_addr); |
|
|
|
evt_data.event = IPA_ROUTE_ADD_EVENT; |
|
data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; |
|
data_addr->iptype = IPA_IP_v6; |
|
|
|
IPACMDBG("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv6 address\n", |
|
data_addr->if_index); |
|
evt_data.evt_data = data_addr; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
/* finish command queue */ |
|
|
|
} |
|
else |
|
{ |
|
IPACM_NL_REPORT_ADDR( "route add default gw \n", msg_ptr->nl_route_info.attr_info.gateway_addr ); |
|
IPACMDBG_H("dev %s \n", dev_name); |
|
IPACM_NL_REPORT_ADDR( "dstIP:", msg_ptr->nl_route_info.attr_info.dst_addr ); |
|
|
|
/* insert to command queue */ |
|
data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); |
|
if(data_addr == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_addr\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
IPACM_EVENT_COPY_ADDR_v4( if_ipipv4_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr); |
|
|
|
evt_data.event = IPA_ROUTE_ADD_EVENT; |
|
data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; |
|
data_addr->iptype = IPA_IP_v4; |
|
data_addr->ipv4_addr = ntohl(if_ipv4_addr); |
|
data_addr->ipv4_addr_gw = ntohl(if_ipv4_addr_gw); |
|
data_addr->ipv4_addr_mask = ntohl(if_ipipv4_addr_mask); |
|
|
|
IPACMDBG_H("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv4 addr:0x%x, mask: 0x%x and gw: 0x%x\n", |
|
data_addr->if_index, |
|
data_addr->ipv4_addr, |
|
data_addr->ipv4_addr_mask, |
|
data_addr->ipv4_addr_gw); |
|
evt_data.evt_data = data_addr; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
/* finish command queue */ |
|
} |
|
} |
|
} |
|
|
|
/* ipv6 routing table */ |
|
if((AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) && |
|
(msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) && |
|
(msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_KERNEL) && |
|
(msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) |
|
{ |
|
IPACMDBG("\n GOT valid v6-RTM_NEWROUTE event\n"); |
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface name\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST) |
|
{ |
|
IPACM_NL_REPORT_ADDR( "Route ADD DST:", msg_ptr->nl_route_info.attr_info.dst_addr ); |
|
IPACMDBG("%d, metric %d, dev %s\n", |
|
msg_ptr->nl_route_info.metainfo.rtm_dst_len, |
|
msg_ptr->nl_route_info.attr_info.priority, |
|
dev_name); |
|
|
|
/* insert to command queue */ |
|
data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); |
|
if(data_addr == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_addr\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
|
|
data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]); |
|
data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); |
|
data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); |
|
data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); |
|
|
|
mask_value_v6 = msg_ptr->nl_route_info.metainfo.rtm_dst_len; |
|
for(mask_index = 0; mask_index < 4; mask_index++) |
|
{ |
|
if(mask_value_v6 >= 32) |
|
{ |
|
mask_v6(32, &data_addr->ipv6_addr_mask[mask_index]); |
|
mask_value_v6 -= 32; |
|
} |
|
else |
|
{ |
|
mask_v6(mask_value_v6, &data_addr->ipv6_addr_mask[mask_index]); |
|
mask_value_v6 = 0; |
|
} |
|
} |
|
|
|
IPACMDBG("ADD IPV6 MASK %d: %08x:%08x:%08x:%08x \n", |
|
msg_ptr->nl_route_info.metainfo.rtm_dst_len, |
|
data_addr->ipv6_addr_mask[0], |
|
data_addr->ipv6_addr_mask[1], |
|
data_addr->ipv6_addr_mask[2], |
|
data_addr->ipv6_addr_mask[3]); |
|
|
|
data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]); |
|
data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]); |
|
data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]); |
|
data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]); |
|
|
|
evt_data.event = IPA_ROUTE_ADD_EVENT; |
|
data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; |
|
data_addr->iptype = IPA_IP_v6; |
|
|
|
IPACMDBG("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv6 addr\n", |
|
data_addr->if_index); |
|
evt_data.evt_data = data_addr; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
/* finish command queue */ |
|
} |
|
if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_GATEWAY) |
|
{ |
|
IPACM_NL_REPORT_ADDR( "Route ADD ::/0 Next Hop:", msg_ptr->nl_route_info.attr_info.gateway_addr ); |
|
IPACMDBG(" metric %d, dev %s\n", |
|
msg_ptr->nl_route_info.attr_info.priority, |
|
dev_name); |
|
|
|
/* insert to command queue */ |
|
data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); |
|
if(data_addr == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_addr\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
|
|
data_addr->ipv6_addr[0]=ntohl(data_addr->ipv6_addr[0]); |
|
data_addr->ipv6_addr[1]=ntohl(data_addr->ipv6_addr[1]); |
|
data_addr->ipv6_addr[2]=ntohl(data_addr->ipv6_addr[2]); |
|
data_addr->ipv6_addr[3]=ntohl(data_addr->ipv6_addr[3]); |
|
|
|
IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
|
|
data_addr->ipv6_addr_mask[0]=ntohl(data_addr->ipv6_addr_mask[0]); |
|
data_addr->ipv6_addr_mask[1]=ntohl(data_addr->ipv6_addr_mask[1]); |
|
data_addr->ipv6_addr_mask[2]=ntohl(data_addr->ipv6_addr_mask[2]); |
|
data_addr->ipv6_addr_mask[3]=ntohl(data_addr->ipv6_addr_mask[3]); |
|
|
|
evt_data.event = IPA_ROUTE_ADD_EVENT; |
|
data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; |
|
data_addr->iptype = IPA_IP_v6; |
|
|
|
IPACMDBG("posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv6 address\n", |
|
data_addr->if_index); |
|
evt_data.evt_data = data_addr; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
/* finish command queue */ |
|
} |
|
} |
|
break; |
|
|
|
case RTM_DELROUTE: |
|
if(IPACM_SUCCESS != ipa_nl_decode_rtm_route(buffer, buflen, &(msg_ptr->nl_route_info))) |
|
{ |
|
IPACMERR("Failed to decode rtm route message\n"); |
|
return IPACM_FAILURE; |
|
} |
|
/* take care of route delete of default route & uniroute */ |
|
if((msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) && |
|
((msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) || |
|
(msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_RA)) && |
|
(msg_ptr->nl_route_info.metainfo.rtm_scope == 0) && |
|
(msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) |
|
{ |
|
|
|
if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST) |
|
{ |
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface name\n"); |
|
return IPACM_FAILURE; |
|
} |
|
IPACM_NL_REPORT_ADDR( "route del -host ", msg_ptr->nl_route_info.attr_info.dst_addr); |
|
IPACM_NL_REPORT_ADDR( " gw ", msg_ptr->nl_route_info.attr_info.gateway_addr); |
|
IPACMDBG("dev %s\n", dev_name); |
|
|
|
/* insert to command queue */ |
|
data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); |
|
if(data_addr == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_addr\n"); |
|
return IPACM_FAILURE; |
|
} |
|
IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
temp = (-1); |
|
if_ipipv4_addr_mask = ntohl(temp); |
|
|
|
evt_data.event = IPA_ROUTE_DEL_EVENT; |
|
data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; |
|
data_addr->iptype = IPA_IP_v4; |
|
data_addr->ipv4_addr = ntohl(if_ipv4_addr); |
|
data_addr->ipv4_addr_mask = ntohl(if_ipipv4_addr_mask); |
|
|
|
IPACMDBG_H("Posting event IPA_ROUTE_DEL_EVENT with if index:%d, ipv4 address 0x%x, mask:0x%x\n", |
|
data_addr->if_index, |
|
data_addr->ipv4_addr, |
|
data_addr->ipv4_addr_mask); |
|
evt_data.evt_data = data_addr; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
/* finish command queue */ |
|
} |
|
else |
|
{ |
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface name\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
/* insert to command queue */ |
|
data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); |
|
if(data_addr == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_addr\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
if(AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) |
|
{ |
|
if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_PRIORITY) |
|
{ |
|
IPACMDBG("ip -6 route del default dev %s metric %d\n", |
|
dev_name, |
|
msg_ptr->nl_route_info.attr_info.priority); |
|
} |
|
else |
|
{ |
|
IPACMDBG("ip -6 route del default dev %s\n", dev_name); |
|
} |
|
IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]); |
|
data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); |
|
data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); |
|
data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); |
|
|
|
IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]); |
|
data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]); |
|
data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]); |
|
data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]); |
|
|
|
IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr); |
|
data_addr->ipv6_addr_gw[0] = ntohl(data_addr->ipv6_addr_gw[0]); |
|
data_addr->ipv6_addr_gw[1] = ntohl(data_addr->ipv6_addr_gw[1]); |
|
data_addr->ipv6_addr_gw[2] = ntohl(data_addr->ipv6_addr_gw[2]); |
|
data_addr->ipv6_addr_gw[3] = ntohl(data_addr->ipv6_addr_gw[3]); |
|
IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_route_info.attr_info.gateway_addr); |
|
data_addr->iptype = IPA_IP_v6; |
|
} |
|
else |
|
{ |
|
IPACM_NL_REPORT_ADDR( "route del default gw", msg_ptr->nl_route_info.attr_info.gateway_addr); |
|
IPACMDBG("dev %s\n", dev_name); |
|
|
|
IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr); |
|
|
|
IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
data_addr->ipv4_addr_mask = ntohl(data_addr->ipv4_addr_mask); |
|
|
|
data_addr->iptype = IPA_IP_v4; |
|
} |
|
|
|
evt_data.event = IPA_ROUTE_DEL_EVENT; |
|
data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; |
|
|
|
IPACMDBG_H("Posting IPA_ROUTE_DEL_EVENT with if index:%d\n", |
|
data_addr->if_index); |
|
evt_data.evt_data = data_addr; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
/* finish command queue */ |
|
} |
|
} |
|
|
|
/* ipv6 routing table */ |
|
if((AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) && |
|
(msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) && |
|
(msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_KERNEL) && |
|
(msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) |
|
{ |
|
IPACMDBG("\n GOT valid v6-RTM_DELROUTE event\n"); |
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface name"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST) |
|
{ |
|
IPACM_NL_REPORT_ADDR( "DEL", msg_ptr->nl_route_info.attr_info.dst_addr); |
|
IPACMDBG("/%d, metric %d, dev %s\n", |
|
msg_ptr->nl_route_info.metainfo.rtm_dst_len, |
|
msg_ptr->nl_route_info.attr_info.priority, |
|
dev_name); |
|
|
|
/* insert to command queue */ |
|
data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); |
|
if(data_addr == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_addr\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr); |
|
|
|
data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]); |
|
data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); |
|
data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); |
|
data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); |
|
|
|
mask_value_v6 = msg_ptr->nl_route_info.metainfo.rtm_dst_len; |
|
for(mask_index = 0; mask_index < 4; mask_index++) |
|
{ |
|
IPACMDBG("%dst %d \n", |
|
mask_index, |
|
mask_value_v6); |
|
if(mask_value_v6 >= 32) |
|
{ |
|
mask_v6(32, &data_addr->ipv6_addr_mask[mask_index]); |
|
mask_value_v6 -= 32; |
|
IPACMDBG("%dst: %08x \n", |
|
mask_index, |
|
data_addr->ipv6_addr_mask[mask_index]); |
|
} |
|
else |
|
{ |
|
mask_v6(mask_value_v6, data_addr->ipv6_addr_mask); |
|
mask_value_v6 = 0; |
|
IPACMDBG("%dst: %08x \n", |
|
mask_index, |
|
data_addr->ipv6_addr_mask[mask_index]); |
|
} |
|
} |
|
|
|
IPACMDBG("DEL IPV6 MASK 0st: %08x ", |
|
data_addr->ipv6_addr_mask[0]); |
|
IPACMDBG("1st: %08x ", |
|
data_addr->ipv6_addr_mask[1]); |
|
IPACMDBG("2st: %08x ", |
|
data_addr->ipv6_addr_mask[2]); |
|
IPACMDBG("3st: %08x \n", |
|
data_addr->ipv6_addr_mask[3]); |
|
|
|
data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]); |
|
data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]); |
|
data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]); |
|
data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]); |
|
|
|
evt_data.event = IPA_ROUTE_DEL_EVENT; |
|
data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; |
|
data_addr->iptype = IPA_IP_v6; |
|
|
|
IPACMDBG_H("posting event IPA_ROUTE_DEL_EVENT with if index:%d, ipv4 address\n", |
|
data_addr->if_index); |
|
evt_data.evt_data = data_addr; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
/* finish command queue */ |
|
} |
|
} |
|
break; |
|
|
|
case RTM_NEWNEIGH: |
|
if(IPACM_SUCCESS != ipa_nl_decode_rtm_neigh(buffer, buflen, &(msg_ptr->nl_neigh_info))) |
|
{ |
|
IPACMERR("Failed to decode rtm neighbor message\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_neigh_info.metainfo.ndm_ifindex); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface index\n"); |
|
return IPACM_FAILURE; |
|
} |
|
else |
|
{ |
|
IPACMDBG("\n GOT RTM_NEWNEIGH event (%s) ip %d\n",dev_name,msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family); |
|
} |
|
|
|
/* insert to command queue */ |
|
data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); |
|
if(data_all == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_all\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
memset(data_all, 0, sizeof(ipacm_event_data_all)); |
|
if(msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET6) |
|
{ |
|
IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr); |
|
IPACM_EVENT_COPY_ADDR_v6( data_all->ipv6_addr, msg_ptr->nl_neigh_info.attr_info.local_addr); |
|
|
|
data_all->ipv6_addr[0]=ntohl(data_all->ipv6_addr[0]); |
|
data_all->ipv6_addr[1]=ntohl(data_all->ipv6_addr[1]); |
|
data_all->ipv6_addr[2]=ntohl(data_all->ipv6_addr[2]); |
|
data_all->ipv6_addr[3]=ntohl(data_all->ipv6_addr[3]); |
|
data_all->iptype = IPA_IP_v6; |
|
} |
|
else if (msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET) |
|
{ |
|
IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr); |
|
IPACM_EVENT_COPY_ADDR_v4( data_all->ipv4_addr, msg_ptr->nl_neigh_info.attr_info.local_addr); |
|
data_all->ipv4_addr = ntohl(data_all->ipv4_addr); |
|
data_all->iptype = IPA_IP_v4; |
|
} |
|
else |
|
{ |
|
data_all->iptype = IPA_IP_v6; |
|
} |
|
|
|
IPACMDBG("NDA_LLADDR:MAC %02x:%02x:%02x:%02x:%02x:%02x\n", |
|
(unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[0], |
|
(unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[1], |
|
(unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[2], |
|
(unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[3], |
|
(unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[4], |
|
(unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[5]); |
|
|
|
|
|
memcpy(data_all->mac_addr, |
|
msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr.sa_data, |
|
sizeof(data_all->mac_addr)); |
|
data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex; |
|
/* Add support to replace src-mac as bridge0 mac */ |
|
if((msg_ptr->nl_neigh_info.metainfo.ndm_family == AF_BRIDGE) && |
|
(msg_ptr->nl_neigh_info.metainfo.ndm_state == NUD_PERMANENT)) |
|
{ |
|
/* Posting IPA_BRIDGE_LINK_UP_EVENT event */ |
|
evt_data.event = IPA_BRIDGE_LINK_UP_EVENT; |
|
IPACMDBG_H("posting IPA_BRIDGE_LINK_UP_EVENT (%s):index:%d \n", |
|
dev_name, |
|
data_all->if_index); |
|
} |
|
else |
|
{ |
|
/* Posting new_neigh events for all LAN/WAN clients */ |
|
evt_data.event = IPA_NEW_NEIGH_EVENT; |
|
IPACMDBG_H("posting IPA_NEW_NEIGH_EVENT (%s):index:%d ip-family: %d\n", |
|
dev_name, |
|
data_all->if_index, |
|
msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family); |
|
} |
|
evt_data.evt_data = data_all; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
/* finish command queue */ |
|
break; |
|
|
|
case RTM_DELNEIGH: |
|
if(IPACM_SUCCESS != ipa_nl_decode_rtm_neigh(buffer, buflen, &(msg_ptr->nl_neigh_info))) |
|
{ |
|
IPACMERR("Failed to decode rtm neighbor message\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_neigh_info.metainfo.ndm_ifindex); |
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Error while getting interface index\n"); |
|
return IPACM_FAILURE; |
|
} |
|
else |
|
{ |
|
IPACMDBG("\n GOT RTM_DELNEIGH event (%s) ip %d\n",dev_name,msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family); |
|
} |
|
|
|
/* insert to command queue */ |
|
data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); |
|
if(data_all == NULL) |
|
{ |
|
IPACMERR("unable to allocate memory for event data_all\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
memset(data_all, 0, sizeof(ipacm_event_data_all)); |
|
if(msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET6) |
|
{ |
|
IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr); |
|
IPACM_EVENT_COPY_ADDR_v6( data_all->ipv6_addr, msg_ptr->nl_neigh_info.attr_info.local_addr); |
|
|
|
data_all->ipv6_addr[0] = ntohl(data_all->ipv6_addr[0]); |
|
data_all->ipv6_addr[1] = ntohl(data_all->ipv6_addr[1]); |
|
data_all->ipv6_addr[2] = ntohl(data_all->ipv6_addr[2]); |
|
data_all->ipv6_addr[3] = ntohl(data_all->ipv6_addr[3]); |
|
data_all->iptype = IPA_IP_v6; |
|
} |
|
else if (msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET) |
|
{ |
|
IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr); |
|
IPACM_EVENT_COPY_ADDR_v4( data_all->ipv4_addr, msg_ptr->nl_neigh_info.attr_info.local_addr); |
|
data_all->ipv4_addr = ntohl(data_all->ipv4_addr); |
|
data_all->iptype = IPA_IP_v4; |
|
} |
|
else |
|
{ |
|
data_all->iptype = IPA_IP_v6; |
|
} |
|
|
|
IPACMDBG("NDA_LLADDR:MAC %02x:%02x:%02x:%02x:%02x:%02x\n", |
|
(unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[0], |
|
(unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[1], |
|
(unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[2], |
|
(unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[3], |
|
(unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[4], |
|
(unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[5]); |
|
|
|
memcpy(data_all->mac_addr, |
|
msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr.sa_data, |
|
sizeof(data_all->mac_addr)); |
|
evt_data.event = IPA_DEL_NEIGH_EVENT; |
|
data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex; |
|
|
|
IPACMDBG_H("posting IPA_DEL_NEIGH_EVENT (%s):index:%d ip-family: %d\n", |
|
dev_name, |
|
data_all->if_index, |
|
msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family); |
|
evt_data.evt_data = data_all; |
|
IPACM_EvtDispatcher::PostEvt(&evt_data); |
|
/* finish command queue */ |
|
break; |
|
|
|
default: |
|
IPACMDBG(" ignore NL event %d!!!\n ", nlh->nlmsg_type); |
|
break; |
|
|
|
} |
|
nlh = NLMSG_NEXT(nlh, buflen); |
|
} |
|
|
|
return IPACM_SUCCESS; |
|
} |
|
|
|
|
|
/* Virtual function registered to receive incoming messages over the NETLINK routing socket*/ |
|
int ipa_nl_recv_msg(int fd) |
|
{ |
|
struct msghdr *msghdr = NULL; |
|
struct iovec *iov = NULL; |
|
unsigned int msglen = 0; |
|
ipa_nl_msg_t *nlmsg = NULL; |
|
|
|
nlmsg = (ipa_nl_msg_t *)malloc(sizeof(ipa_nl_msg_t)); |
|
if(NULL == nlmsg) |
|
{ |
|
IPACMERR("Failed alloc of nlmsg \n"); |
|
goto error; |
|
} |
|
else |
|
{ |
|
if(IPACM_SUCCESS != ipa_nl_recv(fd, &msghdr, &msglen)) |
|
{ |
|
IPACMERR("Failed to receive nl message \n"); |
|
goto error; |
|
} |
|
|
|
if(msghdr== NULL) |
|
{ |
|
IPACMERR(" failed to get msghdr\n"); |
|
goto error; |
|
} |
|
|
|
iov = msghdr->msg_iov; |
|
|
|
memset(nlmsg, 0, sizeof(ipa_nl_msg_t)); |
|
if(IPACM_SUCCESS != ipa_nl_decode_nlmsg((char *)iov->iov_base, msglen, nlmsg)) |
|
{ |
|
IPACMERR("Failed to decode nl message \n"); |
|
goto error; |
|
} |
|
/* Release NetLink message buffer */ |
|
if(msghdr) |
|
{ |
|
ipa_nl_release_msg(msghdr); |
|
} |
|
if(nlmsg) |
|
{ |
|
free(nlmsg); |
|
} |
|
} |
|
|
|
return IPACM_SUCCESS; |
|
|
|
error: |
|
if(msghdr) |
|
{ |
|
ipa_nl_release_msg(msghdr); |
|
} |
|
if(nlmsg) |
|
{ |
|
free(nlmsg); |
|
} |
|
|
|
return IPACM_FAILURE; |
|
} |
|
|
|
/* get ipa interface name */ |
|
int ipa_get_if_name |
|
( |
|
char *if_name, |
|
int if_index |
|
) |
|
{ |
|
int fd; |
|
struct ifreq ifr; |
|
|
|
if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) |
|
{ |
|
IPACMERR("get interface name socket create failed \n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
memset(&ifr, 0, sizeof(struct ifreq)); |
|
ifr.ifr_ifindex = if_index; |
|
IPACMDBG("Interface index %d\n", if_index); |
|
|
|
if(ioctl(fd, SIOCGIFNAME, &ifr) < 0) |
|
{ |
|
IPACMERR("call_ioctl_on_dev: ioctl failed:\n"); |
|
close(fd); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
(void)strncpy(if_name, ifr.ifr_name, sizeof(ifr.ifr_name)); |
|
IPACMDBG("interface name %s\n", ifr.ifr_name); |
|
close(fd); |
|
|
|
return IPACM_SUCCESS; |
|
} |
|
|
|
/* Initialization routine for listener on NetLink sockets interface */ |
|
int ipa_nl_listener_init |
|
( |
|
unsigned int nl_type, |
|
unsigned int nl_groups, |
|
ipa_nl_sk_fd_set_info_t *sk_fdset, |
|
ipa_sock_thrd_fd_read_f read_f |
|
) |
|
{ |
|
ipa_nl_sk_info_t sk_info; |
|
int ret_val; |
|
|
|
memset(&sk_info, 0, sizeof(ipa_nl_sk_info_t)); |
|
IPACMDBG_H("Entering IPA NL listener init\n"); |
|
|
|
if(ipa_nl_open_socket(&sk_info, nl_type, nl_groups) == IPACM_SUCCESS) |
|
{ |
|
IPACMDBG_H("IPA Open netlink socket succeeds\n"); |
|
} |
|
else |
|
{ |
|
IPACMERR("Netlink socket open failed\n"); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
/* Add NETLINK socket to the list of sockets that the listener |
|
thread should listen on. */ |
|
|
|
if(ipa_nl_addfd_map(sk_fdset, sk_info.sk_fd, read_f) != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("cannot add nl routing sock for reading\n"); |
|
close(sk_info.sk_fd); |
|
return IPACM_FAILURE; |
|
} |
|
|
|
/* Start the socket listener thread */ |
|
ret_val = ipa_nl_sock_listener_start(sk_fdset); |
|
|
|
if(ret_val != IPACM_SUCCESS) |
|
{ |
|
IPACMERR("Failed to start NL listener\n"); |
|
} |
|
|
|
return IPACM_SUCCESS; |
|
} |
|
|
|
/* find the newroute subnet mask */ |
|
int find_mask(int ip_v4_last, int *mask_value) |
|
{ |
|
|
|
switch(ip_v4_last) |
|
{ |
|
|
|
case 3: |
|
*mask_value = 252; |
|
return IPACM_SUCCESS; |
|
break; |
|
|
|
case 7: |
|
*mask_value = 248; |
|
return IPACM_SUCCESS; |
|
break; |
|
|
|
case 15: |
|
*mask_value = 240; |
|
return IPACM_SUCCESS; |
|
break; |
|
|
|
case 31: |
|
*mask_value = 224; |
|
return IPACM_SUCCESS; |
|
break; |
|
|
|
case 63: |
|
*mask_value = 192; |
|
return IPACM_SUCCESS; |
|
break; |
|
|
|
case 127: |
|
*mask_value = 128; |
|
return IPACM_SUCCESS; |
|
break; |
|
|
|
case 255: |
|
*mask_value = 0; |
|
return IPACM_SUCCESS; |
|
break; |
|
|
|
default: |
|
return IPACM_FAILURE; |
|
break; |
|
|
|
} |
|
} |
|
|
|
/* map mask value for ipv6 */ |
|
int mask_v6(int index, uint32_t *mask) |
|
{ |
|
switch(index) |
|
{ |
|
|
|
case 0: |
|
*mask = 0x00000000; |
|
return IPACM_SUCCESS; |
|
break; |
|
case 4: |
|
*mask = 0xf0000000; |
|
return IPACM_SUCCESS; |
|
break; |
|
case 8: |
|
*mask = 0xff000000; |
|
return IPACM_SUCCESS; |
|
break; |
|
case 12: |
|
*mask = 0xfff00000; |
|
return IPACM_SUCCESS; |
|
break; |
|
case 16: |
|
*mask = 0xffff0000; |
|
return IPACM_SUCCESS; |
|
break; |
|
case 20: |
|
*mask = 0xfffff000; |
|
return IPACM_SUCCESS; |
|
break; |
|
case 24: |
|
*mask = 0xffffff00; |
|
return IPACM_SUCCESS; |
|
break; |
|
case 28: |
|
*mask = 0xfffffff0; |
|
return IPACM_SUCCESS; |
|
break; |
|
case 32: |
|
*mask = 0xffffffff; |
|
return IPACM_SUCCESS; |
|
break; |
|
default: |
|
return IPACM_FAILURE; |
|
break; |
|
|
|
} |
|
} |
|
|
|
|
|
|