diff options
author | Bruno Martins <bgcngm@gmail.com> | 2018-01-08 12:51:07 +0000 |
---|---|---|
committer | Davide Garberi <dade.garberi@gmail.com> | 2018-01-20 09:30:21 +0100 |
commit | 1c67f47d4a205e12650dcb6255c00bafc0046082 (patch) | |
tree | 72bb48ca2152cb2295b0f8de39497490d8616f6f /data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp | |
parent | 6b0c862328f58e523e2a6efa667a2f4b3a609bf3 (diff) |
msm8996-common: Import IPACM back
* QC package: LA.UM.6.5.r1-05300-8x96.0
* Squashed with commits 08e2a5b9b, 055b183 and 8fcf57b
Change-Id: I2f7a792dc0155986e065d1bf79e1f08370c3d79c
Signed-off-by: Davide Garberi <dade.garberi@gmail.com>
Diffstat (limited to 'data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp')
-rw-r--r-- | data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp | 1050 |
1 files changed, 1050 insertions, 0 deletions
diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp new file mode 100644 index 0000000..d93cef6 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp @@ -0,0 +1,1050 @@ +/* +Copyright (c) 2013-2017, 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_Main.cpp + + @brief + This file implements the IPAM functionality. + + @Author + Skylar Chang + +*/ +/****************************************************************************** + + IPCM_MAIN.C + +******************************************************************************/ + +#include <sys/socket.h> +#include <signal.h> +#include <fcntl.h> +#include <pthread.h> +#include <sys/ioctl.h> +#include <linux/if.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> +#include <fcntl.h> +#include <sys/inotify.h> +#include <stdlib.h> +#include <signal.h> +#include "linux/ipa_qmi_service_v01.h" + +#include "IPACM_CmdQueue.h" +#include "IPACM_EvtDispatcher.h" +#include "IPACM_Defs.h" +#include "IPACM_Neighbor.h" +#include "IPACM_IfaceManager.h" +#include "IPACM_Log.h" + +#include "IPACM_ConntrackListener.h" +#include "IPACM_ConntrackClient.h" +#include "IPACM_Netlink.h" + +#ifdef FEATURE_IPACM_HAL +#include "IPACM_OffloadManager.h" +#include <HAL.h> +#endif + +/* not defined(FEATURE_IPA_ANDROID)*/ +#ifndef FEATURE_IPA_ANDROID +#include "IPACM_LanToLan.h" +#endif + +#define IPA_DRIVER "/dev/ipa" + +#define IPACM_FIREWALL_FILE_NAME "mobileap_firewall.xml" +#define IPACM_CFG_FILE_NAME "IPACM_cfg.xml" +#ifdef FEATURE_IPA_ANDROID +#define IPACM_PID_FILE "/data/vendor/ipa/ipacm.pid" +#define IPACM_DIR_NAME "/data" +#else/* defined(FEATURE_IPA_ANDROID) */ +#define IPACM_PID_FILE "/etc/ipacm.pid" +#define IPACM_DIR_NAME "/etc" +#endif /* defined(NOT FEATURE_IPA_ANDROID)*/ +#define IPACM_NAME "ipacm" + +#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event)) +#define INOTIFY_BUF_LEN (INOTIFY_EVENT_SIZE + 2*sizeof(IPACM_FIREWALL_FILE_NAME)) + +#define IPA_DRIVER_WLAN_EVENT_MAX_OF_ATTRIBS 3 +#define IPA_DRIVER_WLAN_EVENT_SIZE (sizeof(struct ipa_wlan_msg_ex)+ IPA_DRIVER_WLAN_EVENT_MAX_OF_ATTRIBS*sizeof(ipa_wlan_hdr_attrib_val)) +#define IPA_DRIVER_PIPE_STATS_EVENT_SIZE (sizeof(struct ipa_get_data_stats_resp_msg_v01)) +#define IPA_DRIVER_WLAN_META_MSG (sizeof(struct ipa_msg_meta)) +#define IPA_DRIVER_WLAN_BUF_LEN (IPA_DRIVER_PIPE_STATS_EVENT_SIZE + IPA_DRIVER_WLAN_META_MSG) + +uint32_t ipacm_event_stats[IPACM_EVENT_MAX]; +bool ipacm_logging = true; + +void ipa_is_ipacm_running(void); +int ipa_get_if_index(char *if_name, int *if_index); + +IPACM_Neighbor *neigh; +IPACM_IfaceManager *ifacemgr; + +#ifdef FEATURE_IPACM_HAL + IPACM_OffloadManager* OffloadMng; + HAL *hal; +#endif + +/* start netlink socket monitor*/ +void* netlink_start(void *param) +{ + param = NULL; + ipa_nl_sk_fd_set_info_t sk_fdset; + int ret_val = 0; + memset(&sk_fdset, 0, sizeof(ipa_nl_sk_fd_set_info_t)); + IPACMDBG_H("netlink starter memset sk_fdset succeeds\n"); + ret_val = ipa_nl_listener_init(NETLINK_ROUTE, (RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_LINK | + RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NEIGH | + RTNLGRP_IPV6_PREFIX), + &sk_fdset, ipa_nl_recv_msg); + + if (ret_val != IPACM_SUCCESS) + { + IPACMERR("Failed to initialize IPA netlink event listener\n"); + return NULL; + } + + return NULL; +} + +/* start firewall-rule monitor*/ +void* firewall_monitor(void *param) +{ + int length; + int wd; + char buffer[INOTIFY_BUF_LEN]; + int inotify_fd; + ipacm_cmd_q_data evt_data; + uint32_t mask = IN_MODIFY | IN_MOVE; + + param = NULL; + inotify_fd = inotify_init(); + if (inotify_fd < 0) + { + PERROR("inotify_init"); + } + + IPACMDBG_H("Waiting for nofications in dir %s with mask: 0x%x\n", IPACM_DIR_NAME, mask); + + wd = inotify_add_watch(inotify_fd, + IPACM_DIR_NAME, + mask); + + while (1) + { + length = read(inotify_fd, buffer, INOTIFY_BUF_LEN); + if (length < 0) + { + IPACMERR("inotify read() error return length: %d and mask: 0x%x\n", length, mask); + continue; + } + + struct inotify_event* event; + event = (struct inotify_event*)malloc(length); + if(event == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memset(event, 0, length); + memcpy(event, buffer, length); + + if (event->len > 0) + { + if ( (event->mask & IN_MODIFY) || (event->mask & IN_MOVE)) + { + if (event->mask & IN_ISDIR) + { + IPACMDBG_H("The directory %s was 0x%x\n", event->name, event->mask); + } + else if (!strncmp(event->name, IPACM_FIREWALL_FILE_NAME, event->len)) // firewall_rule change + { + IPACMDBG_H("File \"%s\" was 0x%x\n", event->name, event->mask); + IPACMDBG_H("The interested file %s .\n", IPACM_FIREWALL_FILE_NAME); + + evt_data.event = IPA_FIREWALL_CHANGE_EVENT; + evt_data.evt_data = NULL; + + /* Insert IPA_FIREWALL_CHANGE_EVENT to command queue */ + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + else if (!strncmp(event->name, IPACM_CFG_FILE_NAME, event->len)) // IPACM_configuration change + { + IPACMDBG_H("File \"%s\" was 0x%x\n", event->name, event->mask); + IPACMDBG_H("The interested file %s .\n", IPACM_CFG_FILE_NAME); + + evt_data.event = IPA_CFG_CHANGE_EVENT; + evt_data.evt_data = NULL; + + /* Insert IPA_FIREWALL_CHANGE_EVENT to command queue */ + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + } + IPACMDBG_H("Received monitoring event %s.\n", event->name); + } + free(event); + } + + (void)inotify_rm_watch(inotify_fd, wd); + (void)close(inotify_fd); + return NULL; +} + + +/* start IPACM wan-driver notifier */ +void* ipa_driver_msg_notifier(void *param) +{ + int length, fd, cnt; + char buffer[IPA_DRIVER_WLAN_BUF_LEN]; + struct ipa_msg_meta event_hdr; + struct ipa_ecm_msg event_ecm; + struct ipa_wan_msg event_wan; + struct ipa_wlan_msg_ex event_ex_o; + struct ipa_wlan_msg *event_wlan=NULL; + struct ipa_wlan_msg_ex *event_ex= NULL; + struct ipa_get_data_stats_resp_msg_v01 event_data_stats; + struct ipa_get_apn_data_stats_resp_msg_v01 event_network_stats; + IPACM_OffloadManager* OffloadMng; + + ipacm_cmd_q_data evt_data; + ipacm_event_data_mac *data = NULL; + ipacm_event_data_fid *data_fid = NULL; + ipacm_event_data_iptype *data_iptype = NULL; + ipacm_event_data_wlan_ex *data_ex; + ipa_get_data_stats_resp_msg_v01 *data_tethering_stats = NULL; + ipa_get_apn_data_stats_resp_msg_v01 *data_network_stats = NULL; +#ifdef FEATURE_L2TP + ipa_ioc_vlan_iface_info *vlan_info = NULL; + ipa_ioc_l2tp_vlan_mapping_info *mapping = NULL; +#endif + ipacm_cmd_q_data new_neigh_evt; + ipacm_event_data_all* new_neigh_data; + + param = NULL; + fd = open(IPA_DRIVER, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DRIVER); + return NULL; + } + + while (1) + { + IPACMDBG_H("Waiting for nofications from IPA driver \n"); + memset(buffer, 0, sizeof(buffer)); + memset(&evt_data, 0, sizeof(evt_data)); + memset(&new_neigh_evt, 0, sizeof(ipacm_cmd_q_data)); + new_neigh_data = NULL; + data = NULL; + data_fid = NULL; + data_tethering_stats = NULL; + data_network_stats = NULL; + + length = read(fd, buffer, IPA_DRIVER_WLAN_BUF_LEN); + if (length < 0) + { + PERROR("didn't read IPA_driver correctly"); + continue; + } + + memcpy(&event_hdr, buffer,sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Message type: %d\n", event_hdr.msg_type); + IPACMDBG_H("Event header length received: %d\n",event_hdr.msg_len); + + /* Insert WLAN_DRIVER_EVENT to command queue */ + switch (event_hdr.msg_type) + { + + case SW_ROUTING_ENABLE: + IPACMDBG_H("Received SW_ROUTING_ENABLE\n"); + evt_data.event = IPA_SW_ROUTING_ENABLE; + IPACMDBG_H("Not supported anymore\n"); + continue; + + case SW_ROUTING_DISABLE: + IPACMDBG_H("Received SW_ROUTING_DISABLE\n"); + evt_data.event = IPA_SW_ROUTING_DISABLE; + IPACMDBG_H("Not supported anymore\n"); + continue; + + case WLAN_AP_CONNECT: + event_wlan = (struct ipa_wlan_msg *) (buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_AP_CONNECT name: %s\n",event_wlan->name); + IPACMDBG_H("AP Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data_fid\n"); + return NULL; + } + ipa_get_if_index(event_wlan->name, &(data_fid->if_index)); + evt_data.event = IPA_WLAN_AP_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + break; + + case WLAN_AP_DISCONNECT: + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_AP_DISCONNECT name: %s\n",event_wlan->name); + IPACMDBG_H("AP Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data_fid\n"); + return NULL; + } + ipa_get_if_index(event_wlan->name, &(data_fid->if_index)); + evt_data.event = IPA_WLAN_LINK_DOWN_EVENT; + evt_data.evt_data = data_fid; + break; + case WLAN_STA_CONNECT: + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_STA_CONNECT name: %s\n",event_wlan->name); + IPACMDBG_H("STA Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if(data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data_fid\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.event = IPA_WLAN_STA_LINK_UP_EVENT; + evt_data.evt_data = data; + break; + + case WLAN_STA_DISCONNECT: + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_STA_DISCONNECT name: %s\n",event_wlan->name); + IPACMDBG_H("STA Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data_fid\n"); + return NULL; + } + ipa_get_if_index(event_wlan->name, &(data_fid->if_index)); + evt_data.event = IPA_WLAN_LINK_DOWN_EVENT; + evt_data.evt_data = data_fid; + break; + + case WLAN_CLIENT_CONNECT: + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_CLIENT_CONNECT\n"); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if (data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.event = IPA_WLAN_CLIENT_ADD_EVENT; + evt_data.evt_data = data; + break; + + case WLAN_CLIENT_CONNECT_EX: + IPACMDBG_H("Received WLAN_CLIENT_CONNECT_EX\n"); + + memcpy(&event_ex_o, buffer + sizeof(struct ipa_msg_meta),sizeof(struct ipa_wlan_msg_ex)); + if(event_ex_o.num_of_attribs > IPA_DRIVER_WLAN_EVENT_MAX_OF_ATTRIBS) + { + IPACMERR("buffer size overflow\n"); + return NULL; + } + length = sizeof(ipa_wlan_msg_ex)+ event_ex_o.num_of_attribs * sizeof(ipa_wlan_hdr_attrib_val); + IPACMDBG_H("num_of_attribs %d, length %d\n", event_ex_o.num_of_attribs, length); + event_ex = (ipa_wlan_msg_ex *)malloc(length); + if(event_ex == NULL ) + { + IPACMERR("Unable to allocate memory\n"); + return NULL; + } + memcpy(event_ex, buffer + sizeof(struct ipa_msg_meta), length); + data_ex = (ipacm_event_data_wlan_ex *)malloc(sizeof(ipacm_event_data_wlan_ex) + event_ex_o.num_of_attribs * sizeof(ipa_wlan_hdr_attrib_val)); + if (data_ex == NULL) + { + IPACMERR("unable to allocate memory for event data\n"); + return NULL; + } + data_ex->num_of_attribs = event_ex->num_of_attribs; + + memcpy(data_ex->attribs, + event_ex->attribs, + event_ex->num_of_attribs * sizeof(ipa_wlan_hdr_attrib_val)); + + ipa_get_if_index(event_ex->name, &(data_ex->if_index)); + evt_data.event = IPA_WLAN_CLIENT_ADD_EVENT_EX; + evt_data.evt_data = data_ex; + + /* Construct new_neighbor msg with netdev device internally */ + new_neigh_data = (ipacm_event_data_all*)malloc(sizeof(ipacm_event_data_all)); + if(new_neigh_data == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memset(new_neigh_data, 0, sizeof(ipacm_event_data_all)); + new_neigh_data->iptype = IPA_IP_v6; + for(cnt = 0; cnt < event_ex->num_of_attribs; cnt++) + { + if(event_ex->attribs[cnt].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) + { + memcpy(new_neigh_data->mac_addr, event_ex->attribs[cnt].u.mac_addr, sizeof(new_neigh_data->mac_addr)); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_ex->attribs[cnt].u.mac_addr[0], event_ex->attribs[cnt].u.mac_addr[1], event_ex->attribs[cnt].u.mac_addr[2], + event_ex->attribs[cnt].u.mac_addr[3], event_ex->attribs[cnt].u.mac_addr[4], event_ex->attribs[cnt].u.mac_addr[5]); + } + else if(event_ex->attribs[cnt].attrib_type == WLAN_HDR_ATTRIB_STA_ID) + { + IPACMDBG_H("Wlan client id %d\n",event_ex->attribs[cnt].u.sta_id); + } + else + { + IPACMDBG_H("Wlan message has unexpected type!\n"); + } + } + new_neigh_data->if_index = data_ex->if_index; + new_neigh_evt.evt_data = (void*)new_neigh_data; + new_neigh_evt.event = IPA_NEW_NEIGH_EVENT; + free(event_ex); + break; + + case WLAN_CLIENT_DISCONNECT: + IPACMDBG_H("Received WLAN_CLIENT_DISCONNECT\n"); + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if (data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.event = IPA_WLAN_CLIENT_DEL_EVENT; + evt_data.evt_data = data; + break; + + case WLAN_CLIENT_POWER_SAVE_MODE: + IPACMDBG_H("Received WLAN_CLIENT_POWER_SAVE_MODE\n"); + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if (data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.event = IPA_WLAN_CLIENT_POWER_SAVE_EVENT; + evt_data.evt_data = data; + break; + + case WLAN_CLIENT_NORMAL_MODE: + IPACMDBG_H("Received WLAN_CLIENT_NORMAL_MODE\n"); + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if (data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.evt_data = data; + evt_data.event = IPA_WLAN_CLIENT_RECOVER_EVENT; + break; + + case ECM_CONNECT: + memcpy(&event_ecm, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_ecm_msg)); + IPACMDBG_H("Received ECM_CONNECT name: %s\n",event_ecm.name); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_ecm data_fid\n"); + return NULL; + } + data_fid->if_index = event_ecm.ifindex; + evt_data.event = IPA_USB_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + break; + + case ECM_DISCONNECT: + memcpy(&event_ecm, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_ecm_msg)); + IPACMDBG_H("Received ECM_DISCONNECT name: %s\n",event_ecm.name); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_ecm data_fid\n"); + return NULL; + } + data_fid->if_index = event_ecm.ifindex; + evt_data.event = IPA_LINK_DOWN_EVENT; + evt_data.evt_data = data_fid; + break; + /* Add for 8994 Android case */ + case WAN_UPSTREAM_ROUTE_ADD: + memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_wan_msg)); + IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_ADD name: %s, tethered name: %s\n", event_wan.upstream_ifname, event_wan.tethered_ifname); + data_iptype = (ipacm_event_data_iptype *)malloc(sizeof(ipacm_event_data_iptype)); + if(data_iptype == NULL) + { + IPACMERR("unable to allocate memory for event_ecm data_iptype\n"); + return NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_iptype->if_index)); + ipa_get_if_index(event_wan.tethered_ifname, &(data_iptype->if_index_tether)); + data_iptype->iptype = event_wan.ip; +#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN + data_iptype->ipv4_addr_gw = event_wan.ipv4_addr_gw; + data_iptype->ipv6_addr_gw[0] = event_wan.ipv6_addr_gw[0]; + data_iptype->ipv6_addr_gw[1] = event_wan.ipv6_addr_gw[1]; + data_iptype->ipv6_addr_gw[2] = event_wan.ipv6_addr_gw[2]; + data_iptype->ipv6_addr_gw[3] = event_wan.ipv6_addr_gw[3]; + IPACMDBG_H("default gw ipv4 (%x)\n", data_iptype->ipv4_addr_gw); + IPACMDBG_H("IPV6 gateway: %08x:%08x:%08x:%08x \n", + data_iptype->ipv6_addr_gw[0], data_iptype->ipv6_addr_gw[1], data_iptype->ipv6_addr_gw[2], data_iptype->ipv6_addr_gw[3]); +#endif + IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_ADD: fid(%d) tether_fid(%d) ip-type(%d)\n", data_iptype->if_index, + data_iptype->if_index_tether, data_iptype->iptype); + evt_data.event = IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT; + evt_data.evt_data = data_iptype; + break; + case WAN_UPSTREAM_ROUTE_DEL: + memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_wan_msg)); + IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_DEL name: %s, tethered name: %s\n", event_wan.upstream_ifname, event_wan.tethered_ifname); + data_iptype = (ipacm_event_data_iptype *)malloc(sizeof(ipacm_event_data_iptype)); + if(data_iptype == NULL) + { + IPACMERR("unable to allocate memory for event_ecm data_iptype\n"); + return NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_iptype->if_index)); + ipa_get_if_index(event_wan.tethered_ifname, &(data_iptype->if_index_tether)); + data_iptype->iptype = event_wan.ip; + IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_DEL: fid(%d) ip-type(%d)\n", data_iptype->if_index, data_iptype->iptype); + evt_data.event = IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT; + evt_data.evt_data = data_iptype; + break; + /* End of adding for 8994 Android case */ + + /* Add for embms case */ + case WAN_EMBMS_CONNECT: + memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_wan_msg)); + IPACMDBG("Received WAN_EMBMS_CONNECT name: %s\n",event_wan.upstream_ifname); + 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 NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_fid->if_index)); + evt_data.event = IPA_WAN_EMBMS_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + break; + + case WLAN_SWITCH_TO_SCC: + IPACMDBG_H("Received WLAN_SWITCH_TO_SCC\n"); + case WLAN_WDI_ENABLE: + IPACMDBG_H("Received WLAN_WDI_ENABLE\n"); + if (IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACM_Iface::ipacmcfg->isMCC_Mode = false; + evt_data.event = IPA_WLAN_SWITCH_TO_SCC; + break; + } + continue; + case WLAN_SWITCH_TO_MCC: + IPACMDBG_H("Received WLAN_SWITCH_TO_MCC\n"); + case WLAN_WDI_DISABLE: + IPACMDBG_H("Received WLAN_WDI_DISABLE\n"); + if (IPACM_Iface::ipacmcfg->isMCC_Mode == false) + { + IPACM_Iface::ipacmcfg->isMCC_Mode = true; + evt_data.event = IPA_WLAN_SWITCH_TO_MCC; + break; + } + continue; + + case WAN_XLAT_CONNECT: + memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), + sizeof(struct ipa_wan_msg)); + IPACMDBG_H("Received WAN_XLAT_CONNECT name: %s\n", + event_wan.upstream_ifname); + + /* post IPA_LINK_UP_EVENT event + * may be WAN interface is not up + */ + data_fid = (ipacm_event_data_fid *)calloc(1, sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for xlat event\n"); + return NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_fid->if_index)); + evt_data.event = IPA_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + IPACMDBG_H("Posting IPA_LINK_UP_EVENT event:%d\n", evt_data.event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + + /* post IPA_WAN_XLAT_CONNECT_EVENT event */ + memset(&evt_data, 0, sizeof(evt_data)); + data_fid = (ipacm_event_data_fid *)calloc(1, sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for xlat event\n"); + return NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_fid->if_index)); + evt_data.event = IPA_WAN_XLAT_CONNECT_EVENT; + evt_data.evt_data = data_fid; + IPACMDBG_H("Posting IPA_WAN_XLAT_CONNECT_EVENT event:%d\n", evt_data.event); + break; + + case IPA_TETHERING_STATS_UPDATE_STATS: + memcpy(&event_data_stats, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_get_data_stats_resp_msg_v01)); + data_tethering_stats = (ipa_get_data_stats_resp_msg_v01 *)malloc(sizeof(struct ipa_get_data_stats_resp_msg_v01)); + if(data_tethering_stats == NULL) + { + IPACMERR("unable to allocate memory for event data_tethering_stats\n"); + return NULL; + } + memcpy(data_tethering_stats, + &event_data_stats, + sizeof(struct ipa_get_data_stats_resp_msg_v01)); + IPACMDBG("Received IPA_TETHERING_STATS_UPDATE_STATS ipa_stats_type: %d\n",data_tethering_stats->ipa_stats_type); + IPACMDBG("Received %d UL, %d DL pipe stats\n",data_tethering_stats->ul_src_pipe_stats_list_len, data_tethering_stats->dl_dst_pipe_stats_list_len); + evt_data.event = IPA_TETHERING_STATS_UPDATE_EVENT; + evt_data.evt_data = data_tethering_stats; + break; + + case IPA_TETHERING_STATS_UPDATE_NETWORK_STATS: + memcpy(&event_network_stats, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_get_apn_data_stats_resp_msg_v01)); + data_network_stats = (ipa_get_apn_data_stats_resp_msg_v01 *)malloc(sizeof(ipa_get_apn_data_stats_resp_msg_v01)); + if(data_network_stats == NULL) + { + IPACMERR("unable to allocate memory for event data_network_stats\n"); + return NULL; + } + memcpy(data_network_stats, + &event_network_stats, + sizeof(struct ipa_get_apn_data_stats_resp_msg_v01)); + IPACMDBG("Received %d apn network stats \n", data_network_stats->apn_data_stats_list_len); + evt_data.event = IPA_NETWORK_STATS_UPDATE_EVENT; + evt_data.evt_data = data_network_stats; + break; + +#ifdef FEATURE_IPACM_HAL + case IPA_QUOTA_REACH: + IPACMDBG_H("Received IPA_QUOTA_REACH\n"); + OffloadMng = IPACM_OffloadManager::GetInstance(); + if (OffloadMng->elrInstance == NULL) { + IPACMERR("OffloadMng->elrInstance is NULL, can't forward to framework!\n"); + } else { + IPACMERR("calling OffloadMng->elrInstance->onLimitReached \n"); + OffloadMng->elrInstance->onLimitReached(); + } + continue; + case IPA_SSR_BEFORE_SHUTDOWN: + IPACMDBG_H("Received IPA_SSR_BEFORE_SHUTDOWN\n"); + OffloadMng = IPACM_OffloadManager::GetInstance(); + if (OffloadMng->elrInstance == NULL) { + IPACMERR("OffloadMng->elrInstance is NULL, can't forward to framework!\n"); + } else { + IPACMERR("calling OffloadMng->elrInstance->onOffloadStopped \n"); + OffloadMng->elrInstance->onOffloadStopped(IpaEventRelay::ERROR); + } + /* WA to clean up wlan instances during SSR */ + evt_data.event = IPA_SSR_NOTICE; + evt_data.evt_data = NULL; + break; + case IPA_SSR_AFTER_POWERUP: + IPACMDBG_H("Received IPA_SSR_AFTER_POWERUP\n"); + OffloadMng = IPACM_OffloadManager::GetInstance(); + if (OffloadMng->elrInstance == NULL) { + IPACMERR("OffloadMng->elrInstance is NULL, can't forward to framework!\n"); + } else { + IPACMERR("calling OffloadMng->elrInstance->onOffloadSupportAvailable \n"); + OffloadMng->elrInstance->onOffloadSupportAvailable(); + } + continue; +#endif +#ifdef FEATURE_L2TP + case ADD_VLAN_IFACE: + vlan_info = (ipa_ioc_vlan_iface_info *)malloc(sizeof(*vlan_info)); + if(vlan_info == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memcpy(vlan_info, buffer + sizeof(struct ipa_msg_meta), sizeof(*vlan_info)); + evt_data.event = IPA_ADD_VLAN_IFACE; + evt_data.evt_data = vlan_info; + break; + + case DEL_VLAN_IFACE: + vlan_info = (ipa_ioc_vlan_iface_info *)malloc(sizeof(*vlan_info)); + if(vlan_info == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memcpy(vlan_info, buffer + sizeof(struct ipa_msg_meta), sizeof(*vlan_info)); + evt_data.event = IPA_DEL_VLAN_IFACE; + evt_data.evt_data = vlan_info; + break; + + case ADD_L2TP_VLAN_MAPPING: + mapping = (ipa_ioc_l2tp_vlan_mapping_info *)malloc(sizeof(*mapping)); + if(mapping == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memcpy(mapping, buffer + sizeof(struct ipa_msg_meta), sizeof(*mapping)); + evt_data.event = IPA_ADD_L2TP_VLAN_MAPPING; + evt_data.evt_data = mapping; + break; + + case DEL_L2TP_VLAN_MAPPING: + mapping = (ipa_ioc_l2tp_vlan_mapping_info *)malloc(sizeof(*mapping)); + if(mapping == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memcpy(mapping, buffer + sizeof(struct ipa_msg_meta), sizeof(*mapping)); + evt_data.event = IPA_DEL_L2TP_VLAN_MAPPING; + evt_data.evt_data = mapping; + break; +#endif + default: + IPACMDBG_H("Unhandled message type: %d\n", event_hdr.msg_type); + continue; + + } + /* finish command queue */ + IPACMDBG_H("Posting event:%d\n", evt_data.event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* push new_neighbor with netdev device internally */ + if(new_neigh_data != NULL) + { + IPACMDBG_H("Internally post event IPA_NEW_NEIGH_EVENT\n"); + IPACM_EvtDispatcher::PostEvt(&new_neigh_evt); + } + } + + (void)close(fd); + return NULL; +} + +void IPACM_Sig_Handler(int sig) +{ + ipacm_cmd_q_data evt_data; + + printf("Received Signal: %d\n", sig); + memset(&evt_data, 0, sizeof(evt_data)); + + switch(sig) + { + case SIGUSR1: + IPACMDBG_H("Received SW_ROUTING_ENABLE request \n"); + evt_data.event = IPA_SW_ROUTING_ENABLE; + IPACM_Iface::ipacmcfg->ipa_sw_rt_enable = true; + break; + + case SIGUSR2: + IPACMDBG_H("Received SW_ROUTING_DISABLE request \n"); + evt_data.event = IPA_SW_ROUTING_DISABLE; + IPACM_Iface::ipacmcfg->ipa_sw_rt_enable = false; + break; + } + /* finish command queue */ + IPACMDBG_H("Posting event:%d\n", evt_data.event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + return; +} + +void RegisterForSignals(void) +{ + + signal(SIGUSR1, IPACM_Sig_Handler); + signal(SIGUSR2, IPACM_Sig_Handler); +} + + +int main(int argc, char **argv) +{ + int ret; + pthread_t netlink_thread = 0, monitor_thread = 0, ipa_driver_thread = 0; + pthread_t cmd_queue_thread = 0; + + /* check if ipacm is already running or not */ + ipa_is_ipacm_running(); + + IPACMDBG_H("In main()\n"); + (void)argc; + (void)argv; + + neigh = new IPACM_Neighbor(); + ifacemgr = new IPACM_IfaceManager(); + +#ifdef FEATURE_IPACM_HAL + OffloadMng = IPACM_OffloadManager::GetInstance(); + hal = HAL::makeIPAHAL(1, OffloadMng); + IPACMDBG_H(" START IPACM_OffloadManager and link to android framework\n"); +#endif + +#ifdef FEATURE_ETH_BRIDGE_LE + IPACM_LanToLan* lan2lan = IPACM_LanToLan::get_instance(); +#endif + + CtList = new IPACM_ConntrackListener(); + + IPACMDBG_H("Staring IPA main\n"); + IPACMDBG_H("ipa_cmdq_successful\n"); + + + RegisterForSignals(); + + if (IPACM_SUCCESS == cmd_queue_thread) + { + ret = pthread_create(&cmd_queue_thread, NULL, MessageQueue::Process, NULL); + if (IPACM_SUCCESS != ret) + { + IPACMERR("unable to command queue thread\n"); + return ret; + } + IPACMDBG_H("created command queue thread\n"); + if(pthread_setname_np(cmd_queue_thread, "cmd queue process") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + if (IPACM_SUCCESS == netlink_thread) + { + ret = pthread_create(&netlink_thread, NULL, netlink_start, NULL); + if (IPACM_SUCCESS != ret) + { + IPACMERR("unable to create netlink thread\n"); + return ret; + } + IPACMDBG_H("created netlink thread\n"); + if(pthread_setname_np(netlink_thread, "netlink socket") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + /* Enable Firewall support only on MDM targets */ +#ifndef FEATURE_IPA_ANDROID + if (IPACM_SUCCESS == monitor_thread) + { + ret = pthread_create(&monitor_thread, NULL, firewall_monitor, NULL); + if (IPACM_SUCCESS != ret) + { + IPACMERR("unable to create monitor thread\n"); + return ret; + } + IPACMDBG_H("created firewall monitor thread\n"); + if(pthread_setname_np(monitor_thread, "firewall cfg process") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } +#endif + + if (IPACM_SUCCESS == ipa_driver_thread) + { + ret = pthread_create(&ipa_driver_thread, NULL, ipa_driver_msg_notifier, NULL); + if (IPACM_SUCCESS != ret) + { + IPACMERR("unable to create ipa_driver_wlan thread\n"); + return ret; + } + IPACMDBG_H("created ipa_driver_wlan thread\n"); + if(pthread_setname_np(ipa_driver_thread, "ipa driver ntfy") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + pthread_join(cmd_queue_thread, NULL); + pthread_join(netlink_thread, NULL); + pthread_join(monitor_thread, NULL); + pthread_join(ipa_driver_thread, NULL); + return IPACM_SUCCESS; +} + +/*=========================================================================== + FUNCTION ipa_is_ipacm_running +===========================================================================*/ +/*! +@brief + Determine whether there's already an IPACM process running, if so, terminate + the current one + +@return + None + +@note + +- Dependencies + - None + +- Side Effects + - None +*/ +/*=========================================================================*/ + +void ipa_is_ipacm_running(void) { + + int fd; + struct flock lock; + int retval; + + fd = open(IPACM_PID_FILE, O_RDWR | O_CREAT, 0600); + if ( fd <= 0 ) + { + IPACMERR("Failed to open %s, error is %d - %s\n", + IPACM_PID_FILE, errno, strerror(errno)); + exit(0); + } + + /* + * Getting an exclusive Write lock on the file, if it fails, + * it means that another instance of IPACM is running and it + * got the lock before us. + */ + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_WRLCK; + retval = fcntl(fd, F_SETLK, &lock); + + if (retval != 0) + { + retval = fcntl(fd, F_GETLK, &lock); + if (retval == 0) + { + IPACMERR("Unable to get lock on file %s (my PID %d), PID %d already has it\n", + IPACM_PID_FILE, getpid(), lock.l_pid); + close(fd); + exit(0); + } + } + else + { + IPACMERR("PID %d is IPACM main process\n", getpid()); + } + + return; +} + +/*=========================================================================== + FUNCTION ipa_get_if_index +===========================================================================*/ +/*! +@brief + get ipa interface index by given the interface name + +@return + IPACM_SUCCESS or IPA_FALUIRE + +@note + +- Dependencies + - None + +- Side Effects + - None +*/ +/*=========================================================================*/ +int ipa_get_if_index +( + char *if_name, + int *if_index + ) +{ + int fd; + struct ifreq ifr; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + PERROR("get interface index socket create failed"); + return IPACM_FAILURE; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + + (void)strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); + + if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) + { + IPACMERR("call_ioctl_on_dev: ioctl failed: can't find device %s",if_name); + *if_index = -1; + close(fd); + return IPACM_FAILURE; + } + + *if_index = ifr.ifr_ifindex; + close(fd); + return IPACM_SUCCESS; +} |