aboutsummaryrefslogtreecommitdiff
path: root/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp
diff options
context:
space:
mode:
authorBruno Martins <bgcngm@gmail.com>2018-01-08 12:51:07 +0000
committerDavide Garberi <dade.garberi@gmail.com>2018-01-20 09:30:21 +0100
commit1c67f47d4a205e12650dcb6255c00bafc0046082 (patch)
tree72bb48ca2152cb2295b0f8de39497490d8616f6f /data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp
parent6b0c862328f58e523e2a6efa667a2f4b3a609bf3 (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.cpp1050
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;
+}