[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/connectivity/libipsecims/Makefile b/src/connectivity/libipsecims/Makefile
new file mode 100644
index 0000000..4e7063a
--- /dev/null
+++ b/src/connectivity/libipsecims/Makefile
@@ -0,0 +1,39 @@
+CANLIB=libipsec_ims

+VERSION=1

+TARGET= $(CANLIB).so

+

+

+SO_CFLAGS= -shared

+CFLAGS?= -O2

+H_FILE = ${wildcard *.h}

+CUR_SOURCE=${wildcard *.c}

+CUR_OBJS=${patsubst %.c, %.o, $(CUR_SOURCE)}

+

+

+all: $(TARGET)

+

+

+install: install_headers

+	@mkdir -p $(DEST_DIR)/usr/lib

+	install -m 0644 $(CANLIB).so $(DEST_DIR)/usr/lib

+	install -m 0644 $(CANLIB).so.$(VERSION) $(DEST_DIR)/usr/lib

+

+install_headers:

+	@mkdir -p $(DEST_DIR)/usr/include

+	install -m 0644 *.h $(DEST_DIR)/usr/include

+

+

+%.o: %.c

+	$(CC)  -Wall -fPIC $(CFLAGS) -c $^ -o $@

+$(TARGET).$(VERSION) : $(CUR_OBJS)

+	$(CC) -shared -nostartfiles -Wl,-soname,$@ $^ -o $@ $(LDFLAGS) -lpthread -lsncfg -llog

+

+

+

+$(TARGET): $(CANLIB).so.$(VERSION)

+	ln -s $< $@

+

+

+.PHONY: clean

+clean:

+	rm -f $(CANLIB).* $(CUR_OBJS)
\ No newline at end of file
diff --git a/src/connectivity/libipsecims/MediatekProprietary b/src/connectivity/libipsecims/MediatekProprietary
new file mode 100644
index 0000000..e6e7948
--- /dev/null
+++ b/src/connectivity/libipsecims/MediatekProprietary
@@ -0,0 +1,31 @@
+Copyright Statement:

+

+This software/firmware and related documentation ("MediaTek Software") are

+protected under relevant copyright laws. The information contained herein is

+confidential and proprietary to MediaTek Inc. and/or its licensors. Without

+the prior written permission of MediaTek inc. and/or its licensors, any

+reproduction, modification, use or disclosure of MediaTek Software, and

+information contained herein, in whole or in part, shall be strictly

+prohibited.

+

+MediaTek Inc. (C) 2015. All rights reserved.

+

+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES

+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")

+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER

+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL

+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED

+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR

+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH

+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,

+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES

+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.

+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO

+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK

+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE

+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR

+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S

+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE

+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE

+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE

+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
\ No newline at end of file
diff --git a/src/connectivity/libipsecims/rtnl_socket.c b/src/connectivity/libipsecims/rtnl_socket.c
new file mode 100644
index 0000000..538066d
--- /dev/null
+++ b/src/connectivity/libipsecims/rtnl_socket.c
@@ -0,0 +1,152 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include "utils_xfrm.h"
+#include "setkey_xfrm_parse.h"
+#define LOG_TAG "setkey"
+#include <log/log.h>
+#include <cutils/log.h>
+
+
+void rtnl_close_xfrm(struct rtnl_handle_xfrm *rth_xfrm)
+{
+	if (rth_xfrm->fd >= 0) {
+		close(rth_xfrm->fd);
+		rth_xfrm->fd = -1;
+	}
+}
+
+int rtnl_open_byproto_xfrm(struct rtnl_handle_xfrm *rth_xfrm, unsigned subscriptions,
+		      int protocol)
+{
+	//socklen_t addr_len;
+	//int sndbuf = 32768;
+
+	memset(rth_xfrm, 0, sizeof(*rth_xfrm));
+
+	rth_xfrm->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
+	if (rth_xfrm->fd < 0) {
+		ALOGD("Cannot open netlink socket,errno:%d\n",errno);
+		return -1;
+	}
+
+
+	memset(&rth_xfrm->local, 0, sizeof(rth_xfrm->local));
+	rth_xfrm->local.nl_family = AF_NETLINK;
+	rth_xfrm->local.nl_groups = subscriptions;
+
+	if (bind(rth_xfrm->fd, (struct sockaddr*)&rth_xfrm->local, sizeof(rth_xfrm->local)) < 0) {
+		ALOGD("Cannot bind netlink socket\n");
+		return -1;
+	}
+	return 0;
+}
+
+int rtnl_listen_xfrm(struct rtnl_handle_xfrm *rtnl_xfrm, rtnl_filter_t_xfrm handler)
+{
+	int status;
+	struct nlmsghdr *h_xfrm;
+	struct sockaddr_nl nladdr_xfrm;
+	struct iovec iov;
+	struct msghdr msg_xfrm = {
+		.msg_name = &nladdr_xfrm,
+		.msg_namelen = sizeof(nladdr_xfrm),
+		.msg_iov = &iov,
+		.msg_iovlen = 1,
+	};
+	char   buf[16384];
+
+	memset(&nladdr_xfrm, 0, sizeof(nladdr_xfrm));
+	nladdr_xfrm.nl_family = AF_NETLINK;
+	nladdr_xfrm.nl_pid = 0;
+	nladdr_xfrm.nl_groups = 0;
+	iov.iov_base = buf;
+
+	iov.iov_len = sizeof(buf);
+		status = recvmsg(rtnl_xfrm->fd, &msg_xfrm, 0);
+		ALOGD("netlink receive msg status:%d\n",status);
+		if (status < 0) {
+			if (errno == EINTR || errno == EAGAIN || errno == ENOBUFS)
+				return -1;
+		}
+		if (status == 0) {
+			ALOGE("EOF on netlink\n");
+			return -1;
+		}
+		if (msg_xfrm.msg_namelen != sizeof(nladdr_xfrm)) {
+			ALOGE("Sender address length == %d\n", msg_xfrm.msg_namelen);
+			return -1;
+		}
+		for (h_xfrm = (struct nlmsghdr*)buf; status >= sizeof(*h_xfrm); ) {
+			int err;
+			int len = h_xfrm->nlmsg_len;
+			int l = len - sizeof(*h_xfrm);
+
+			if (l<0 || len>status) {
+				if (msg_xfrm.msg_flags & MSG_TRUNC) {
+					ALOGE("Truncated message\n");
+					return -1;
+				}
+				ALOGE("!!!malformed message: len=%d\n", len);
+				return -1;
+			}
+			err = handler(rtnl_xfrm,h_xfrm);
+			if (err == -2) /*no sa & sp entries*/
+			{
+				return err;
+			}
+
+			status -= NLMSG_ALIGN(len);
+			h_xfrm = (struct nlmsghdr*)((char*)h_xfrm + NLMSG_ALIGN(len));
+		}
+
+	return 0;
+}
+
+/*
+  -2: no previous volte_stack policy&& state is set;
+  -1: unknown message type && delete policy or state failed
+   0:  everything is good
+*/
+int rtnl_accept_msg_xfrm(struct rtnl_handle_xfrm * rth ,struct nlmsghdr *n)
+{
+	char pid[128] = {0};
+	property_get("net.ims.volte.pid",pid,"-1");
+	pid_t volte_pid =atoi(pid);
+	/*no previous volte_stack policy&& state is set*/
+	switch (n->nlmsg_type) {
+	case XFRM_MSG_NEWSA:
+	case XFRM_MSG_UPDSA:
+		return xfrm_state_process_delete_exist( rth,n, volte_pid);
+	case XFRM_MSG_NEWPOLICY:
+	case XFRM_MSG_UPDPOLICY:
+		return xfrm_policy_process_delete_exist( rth,n, volte_pid);
+	case XFRM_MSG_EXPIRE:
+	case XFRM_MSG_DELSA:
+	case XFRM_MSG_FLUSHSA:
+	case XFRM_MSG_GETPOLICY:
+	case XFRM_MSG_FLUSHPOLICY:
+	case XFRM_MSG_ACQUIRE:
+	case XFRM_MSG_DELPOLICY:
+	case XFRM_MSG_POLEXPIRE:
+	default:
+		ALOGD("receive netlink message: %08d 0x%08x 0x%08x\n",
+			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
+		break;
+	}
+
+	if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP &&
+	    n->nlmsg_type != NLMSG_DONE) {
+		ALOGE("Unknown message: %08d 0x%08x 0x%08x\n",
+			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
+	}
+	return -2;
+}
+
diff --git a/src/connectivity/libipsecims/setkey_fileio.c b/src/connectivity/libipsecims/setkey_fileio.c
new file mode 100644
index 0000000..5bc8d14
--- /dev/null
+++ b/src/connectivity/libipsecims/setkey_fileio.c
@@ -0,0 +1,1112 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include <linux/capability.h>
+#include <sys/capability.h>
+#include <cutils/properties.h>
+#include "setkey_fileio.h"
+#if 0
+#include "../setkey/log_setky.h"
+#endif
+#define LOG_TAG "setkey"
+#include <log/log.h>
+#include <cutils/log.h>
+
+#if 0
+extern void plog_android(int level, char *format, ...);
+extern int setkey_main(int argc, char ** argv);
+
+#define POLICY_LEN 640
+#define POLICY_MODE 320
+#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
+#define BUFF_SIZE 128
+#define RM_FILE_LEN 64
+
+char setkey_conf[]="/data/misc/setkey/setkey.conf";
+char setkey_conf_bak[]="/data/misc/setkey/setkey_bak.conf";
+char setkey_conf_latest[]="/data/misc/setkey/setkey_latest.conf";
+
+
+static int RemoveString(char * src,char * dst,char * ipsec_type,char * spi_src)
+{
+	FILE *fpSrc = NULL;
+	FILE *fpDst = NULL;
+
+	char achBuf[POLICY_LEN] = {0};
+	fpSrc = fopen(setkey_conf, "rt");
+	if (NULL == fpSrc)
+	{
+		plog_android(LLV_WARNING, "RemoveString:can't open %s,errno:%d",setkey_conf,errno);
+		return -1;
+	}
+	chown(setkey_conf,0,1000);
+	fpDst = fopen(setkey_conf_bak, "wt");
+	if (NULL== fpDst)
+	{
+		plog_android(LLV_WARNING,"RemoveString:Create source file: %s failed,errno:%d\n", setkey_conf_bak,errno);
+		fclose(fpSrc);
+		return -1;
+	}
+	chown(setkey_conf_bak,0,1000);
+	while (!feof(fpSrc))
+	{
+		memset(achBuf, 0, sizeof(achBuf));
+		fgets(achBuf, sizeof(achBuf), fpSrc);
+	/* include below parameter is right*/
+		if ((strstr(achBuf, "add")!=NULL)&&(strstr(achBuf, "spdadd")==NULL)&&(strstr(achBuf, dst)!=NULL)&&(strstr(achBuf,ipsec_type)!=NULL)&&(strstr(achBuf, spi_src)!=NULL))
+		{
+			/*to make sure sequence,first src,then dst*/
+			if(strstr(achBuf, src)<strstr(achBuf, dst))
+				plog_android(LLV_WARNING,"Has found SA,%s,remove it\n",achBuf);
+			else
+				fputs(achBuf, fpDst);
+		} else {
+			fputs(achBuf, fpDst);
+		}
+
+	}
+	fclose(fpSrc);
+	fclose(fpDst);
+
+	return 0;
+}
+
+
+static int RemoveString_SP(char * src,char * dst,int protocol,char * src_port,char * dst_port,char * direction)
+{
+	FILE *fpSrc = NULL;
+	FILE *fpDst = NULL;
+
+        char protocol_str[16]={0};
+	char achBuf[POLICY_LEN] = {0};
+        sprintf(protocol_str,"%d",protocol);
+
+	fpSrc = fopen(setkey_conf, "rt");
+	if (NULL == fpSrc)
+	{
+		plog_android(LLV_WARNING, "RemoveString_SP:can't open %s,errno:%d",setkey_conf,errno);
+		return -1;
+	}
+	chown(setkey_conf,0,1000);
+	fpDst = fopen(setkey_conf_bak, "wt");
+	if (NULL== fpDst)
+	{
+		plog_android(LLV_WARNING,"RemoveString_SP:Create source file: %s failed,errno:%d\n", setkey_conf_bak,errno);
+		fclose(fpSrc);
+		return -1;
+	}
+	chown(setkey_conf_bak,0,1000);
+	while (!feof(fpSrc))
+	{
+		memset(achBuf, 0, sizeof(achBuf));
+		fgets(achBuf, sizeof(achBuf), fpSrc);
+		if ((strstr(achBuf, "spdadd")!=NULL)&&(strstr(achBuf, dst)!=NULL)&&(strstr(achBuf, src)!=NULL)&&(strstr(achBuf, src_port)!=NULL)
+                   &&(strstr(achBuf, dst_port)!=NULL)&&(strstr(achBuf, protocol_str)!=NULL)&&(strstr(achBuf, direction)!=NULL))
+		{
+            if((strstr(achBuf, src)<strstr(achBuf, dst))&&(strstr(achBuf, src_port)<strstr(achBuf, dst_port)))
+		        plog_android(LLV_WARNING,"Has found SP policy,%s,remove it\n",achBuf);
+            else
+                fputs(achBuf, fpDst);
+		}
+		else
+		{
+			fputs(achBuf, fpDst);
+		}
+	}
+	fclose(fpSrc);
+	fclose(fpDst);
+
+	return 0;
+}
+
+
+/* 1: some error; 0: process successfully */
+int shell(char * cmd)
+{
+	FILE * fp = NULL,* fp_exit_code =NULL;
+	int    bufflen;
+	char * buffer = (char *)malloc((BUFF_SIZE));
+	if(buffer == NULL)
+    {
+       plog_android(LLV_WARNING, "run shell command buffer is null");
+       return -1;
+    }
+    char * buffer_retcode =  NULL;
+    char * cmd_exit_code = (char *)malloc((BUFF_SIZE));
+    int    ret_code = 0;
+	if(cmd_exit_code == NULL)
+    {
+       plog_android(LLV_WARNING, "alloc cmd_exit_code failed ");
+       goto ret_sec;
+    }
+	if(cmd == NULL)
+    {
+       plog_android(LLV_WARNING, "run shell command is null");
+       goto ret_fir;
+    }
+	buffer[0] = 0;
+    strcpy(cmd_exit_code,cmd);
+    strcat(cmd_exit_code,";echo ret_code:$?");
+	fp = popen(cmd_exit_code,"r");
+	if(fp == NULL)
+    {
+        plog_android(LLV_WARNING, "can't run shell command");
+        goto ret_fir;
+    }
+    //plog_android(LLV_WARNING, "run shell command:%s ...",cmd);
+    while(fgets(buffer,BUFF_SIZE,fp)!=NULL)
+    {
+        plog_android(LLV_WARNING, "%s",buffer);
+    }
+    buffer_retcode = strstr(buffer,"ret_code:");
+    if(buffer_retcode)
+    {
+        ret_code = atoi(buffer_retcode+strlen("ret_code:"));
+        plog_android(LLV_WARNING, "processing cmd:%s return code:%d",cmd,ret_code);
+    }
+    pclose(fp);
+
+
+ret_fir:
+    if(cmd_exit_code)
+        free(cmd_exit_code);
+ret_sec:
+    if(buffer)
+        free(buffer);
+    return ret_code;
+}
+
+/*rm setkey.conf file*/
+int shell_rm(void)
+{
+    char rm_file[RM_FILE_LEN];
+    int ret = 1;
+    memset(rm_file,0,RM_FILE_LEN);
+    snprintf(rm_file,sizeof(rm_file),"rm %s",setkey_conf);
+    if(access(setkey_conf,0) == 0)
+    {
+        ret = shell(rm_file);
+        if(ret != 0)
+        {
+            plog_android(LLV_WARNING,"shell %s failed,errno:%d",rm_file,errno);
+	    return -1;
+        }
+    }
+    return 0;
+
+}
+
+/*setkey -f setkey.conf */
+int function_setkey(char * file_conf)
+{
+    char * argv[4];
+
+    argv[0] = "setkey";
+    argv[1] = "-f";
+    argv[2] = file_conf;
+    argv[3] = NULL;
+    int ret = setkey_main(3,(char **)argv);
+    if(ret != 0)
+    {
+        plog_android(LLV_WARNING," setkey -f  %s failed,errno:%d",file_conf,errno);
+        return ret;
+    }
+    return 0;
+
+}
+#endif
+/*flush all SA*/
+int setkey_flushSAD(void)
+{
+#if 0
+    char * argv[3];
+
+    argv[0] = "setkey";
+    argv[1] = "-F";
+    argv[2] = NULL;
+    if(shell_rm() == -1)
+    {
+	return -1;
+    }
+
+    int ret = setkey_main(2,(char **)argv);
+    if(ret != 0)
+    {
+        plog_android(LLV_WARNING,"setkey -F failed,errno:%d",errno);
+	return ret;
+    }
+    return 0;
+#endif
+    int ret = setkey_flushSAD_xfrm("esp");
+    return ret;
+}
+
+/*flush all SP*/
+int setkey_flushSPD(void)
+{
+#if 0
+    char * argv[4];
+
+    argv[0] = "setkey";
+    argv[1] = "-F";
+    argv[2] = "-P";
+    argv[3] = NULL;
+    if(shell_rm() == -1)
+    {
+	return -1;
+    }
+    int ret = setkey_main(3,(char **)argv);
+    if(ret != 0)
+    {
+        plog_android(LLV_WARNING,"setkey -FP failed,errno:%d",errno);
+	return ret;
+    }
+    return 0;
+#endif
+    int ret = setkey_flushSPD_xfrm();
+    return ret;
+}
+
+/*delete one SA entry*/
+int setkey_deleteSA(char * src,char * dst,char * ipsec_type,char * spi_src)
+{
+#if 0
+    char delSA[POLICY_LEN];
+    FILE * fd_config = NULL;
+
+
+
+    memset(delSA,0,sizeof(delSA));
+
+    snprintf(delSA,sizeof(delSA),"delete %s %s %s %s;\n",src,dst,ipsec_type,spi_src);
+    fd_config = fopen(setkey_conf_latest, "w+");
+    if(fd_config == NULL)
+    {
+	    plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+	    return -1;
+
+    }
+    chown(setkey_conf_latest,0,1000);
+    fwrite(  delSA, strlen(delSA),1,fd_config);
+    plog_android(LLV_WARNING,"setkey_deleteSA:%s",delSA);
+    fclose(fd_config);
+    if(function_setkey(setkey_conf_latest)== -1)
+        return -1;
+    else
+    {
+    	/*update setkey.conf to record how many pairs of SA have been established*/
+
+        if(RemoveString(src,dst,ipsec_type,spi_src)  == 0)
+        {
+    	    if(shell_rm() == -1)
+            {
+	            return -1;
+            }
+            if(rename(setkey_conf_bak,setkey_conf)<0)
+            {
+                plog_android(LLV_WARNING,"rename setkey.conf failed,errno:%d",errno);
+        	    return -1;
+            }
+        }
+        else
+        {
+            plog_android(LLV_WARNING,"RemoveString failed");
+            return -1;
+        }
+    }
+    return 0;
+#endif
+    int ret = setkey_deleteSA_xfrm(src,dst,ipsec_type,spi_src);
+    return ret;
+}
+
+/*delete one SP entry*/
+int setkey_deleteSP(char * src,char * dst,enum PROTOCOL_TYPE protocol,char * src_port,char * dst_port,char * direction)
+{
+#if 0
+    char delSP[POLICY_LEN];
+
+    FILE * fd_config = NULL;
+
+
+
+    memset(delSP,0,sizeof(delSP));
+
+    snprintf(delSP,sizeof(delSP),"spddelete %s[%s] %s[%s] %d -P %s;\n",src,src_port,dst,dst_port,protocol,direction);
+    fd_config = fopen(setkey_conf_latest, "w+");
+    if(fd_config == NULL)
+    {
+	    plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+	    return -1;
+
+    }
+    chown(setkey_conf_latest,0,1000);
+    fwrite(  delSP, strlen(delSP),1,fd_config);
+    plog_android(LLV_WARNING,"setkey_deleteSP:%s",delSP);
+    fclose(fd_config);
+    if(function_setkey(setkey_conf_latest)==-1)
+    	return -1;
+    else
+    {
+    	/*update setkey.conf to record how many pairs of SP policy have been established*/
+
+        if(RemoveString_SP( src, dst, protocol, src_port, dst_port, direction) == 0)
+        {
+    	    if(shell_rm() == -1)
+            {
+	            return -1;
+            }
+            if(rename(setkey_conf_bak,setkey_conf)<0)
+            {
+                plog_android(LLV_WARNING,"rename setkey.conf failed,errno:%d",errno);
+        	    return -1;
+            }
+        }
+        else
+        {
+            plog_android(LLV_WARNING,"RemoveString---%s failed",delSP);
+            return -1;
+        }
+    }
+    return 0;
+#endif
+	int ret = setkey_deleteSP_xfrm(src,dst,protocol,src_port,dst_port,direction);
+	return ret;
+}
+
+/*dump SA */
+int dump_setkeySA(void)
+{
+/*To do*/
+#if 0
+    char * argv[3];
+
+    argv[0] = "setkey";
+    argv[1] = "-D";
+    argv[2] = NULL;
+    int ret = setkey_main(2,(char **)argv);
+    if(ret != 0)
+    {
+        plog_android(LLV_WARNING," setkey -D failed,errno:%d",errno);
+        return -1;
+    }
+#endif
+    return 0;
+
+}
+
+/*dump SP */
+int dump_setkeySP(void)
+{
+/*To do*/
+#if 0
+   char * argv[4];
+
+    argv[0] = "setkey";
+    argv[1] = "-D";
+    argv[2] = "-P";
+    argv[3] = NULL;
+    int ret = setkey_main(3,(char **)argv);
+    if(ret != 0)
+    {
+        plog_android(LLV_WARNING,"setkey -DP failed,errno:%d",errno);
+        return ret;
+    }
+#endif
+    return 0;
+
+}
+#if 0
+void setkey_get_aid_and_cap() {
+
+        plog_android(LLV_WARNING,"Warning: gid:%d,uid:%d,pid:%d !\n",getgid(),getuid(),getpid());
+	struct __user_cap_header_struct header;
+	struct __user_cap_data_struct cap;
+	header.version = _LINUX_CAPABILITY_VERSION;
+	header.pid = getpid();
+	capget(&header, &cap);
+        plog_android(LLV_WARNING, "Warning: permitted:%x,cap.effective:%x !\n",cap.permitted,cap.effective);
+}
+#endif
+/*set one SA*/
+/*ipsec_type:ah esp
+  mode:transport tunnel
+  encrp_algo_src:encryption algorithm,des-cbc,3des-cbc...
+  encrp_algo_src:key of encryption algorithm
+  intergrity_algo_src:authentication algorithm ,hmac-md5,hmac-sha1
+  intergrity_key_src:key of authentication algorithm
+*/
+int setkey_setSA(char * ip_src,char * ip_dst,char * ipsec_type,char * spi_src,char * mode,
+                 char * encrp_algo_src,char * encrp_key_src,char * intergrity_algo_src,char * intergrity_key_src,int u_id)
+{
+#if 0
+    char sad_policy[POLICY_LEN];
+
+    FILE * fd_config = NULL;
+    FILE * fd_config_tmp = NULL;
+
+    memset(sad_policy,0,sizeof(sad_policy));
+
+    setkey_get_aid_and_cap();
+
+    fd_config_tmp = fopen(setkey_conf_latest, "w+" );
+    if(fd_config_tmp == NULL)
+    {
+	      plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf_latest,errno);
+	      return -1;
+    }
+    chown(setkey_conf_latest,0,1000);
+   if(strcmp(encrp_algo_src,"null")==0)
+    {
+        if(u_id ==0 )
+            snprintf(sad_policy,sizeof(sad_policy),"add %s %s %s %s  -m %s -E null  -A %s %s;\n",ip_src,ip_dst,ipsec_type,spi_src,mode,
+                       intergrity_algo_src,intergrity_key_src);
+        else
+            snprintf(sad_policy,sizeof(sad_policy),"add %s %s %s %s  -u %d -m %s -E null  -A %s %s;\n",ip_src,ip_dst,ipsec_type,spi_src,u_id,mode,
+                       intergrity_algo_src,intergrity_key_src);
+    }
+    else
+    {
+        if(u_id ==0 )
+            snprintf(sad_policy,sizeof(sad_policy),"add %s %s %s %s  -m %s -E %s %s  -A %s %s;\n",ip_src,ip_dst,ipsec_type,spi_src,mode,
+                       encrp_algo_src,encrp_key_src,intergrity_algo_src,intergrity_key_src);
+        else
+            snprintf(sad_policy,sizeof(sad_policy),"add %s %s %s %s -u %d -m %s -E %s %s  -A %s %s;\n",ip_src,ip_dst,ipsec_type,spi_src,u_id,mode,
+                       encrp_algo_src,encrp_key_src,intergrity_algo_src,intergrity_key_src);
+    }
+    fwrite( sad_policy, strlen(sad_policy),1,fd_config_tmp );
+    plog_android(LLV_WARNING,"setkey_SA:%s",sad_policy);
+    fclose(fd_config_tmp);
+
+    if(function_setkey(setkey_conf_latest)==0)
+    {
+        fd_config = fopen(setkey_conf, "a+" );
+        if(fd_config == NULL)
+        {
+	      plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+	      return -1;
+        }
+	chown(setkey_conf,0,1000);
+        fwrite( sad_policy, strlen(sad_policy),1,fd_config );
+        fclose(fd_config);
+    }
+    else
+        return -1;
+
+    return 0;
+#endif
+	int ret = setkey_setSA_xfrm(XFRM_MSG_NEWSA,ip_src,ip_dst,ipsec_type,spi_src,mode,
+                 encrp_algo_src,encrp_key_src,intergrity_algo_src,intergrity_key_src,u_id);
+	return ret;
+}
+int setkey_setSA_update(char * ip_src,char * ip_dst,char * ipsec_type,char * spi_src,char * mode,
+                 char * encrp_algo_src,char * encrp_key_src,char * intergrity_algo_src,char * intergrity_key_src,int u_id)
+{
+	int ret = setkey_setSA_xfrm(XFRM_MSG_UPDSA,ip_src,ip_dst,ipsec_type,spi_src,mode,
+                 encrp_algo_src,encrp_key_src,intergrity_algo_src,intergrity_key_src,u_id);
+	return ret;
+}
+/*set one SP of one direction, just for transport mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+  direction:src->dst */
+int setkey_SP(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * ipsec_type,char * mode, char * direction,int u_id)
+{
+#if 0
+    char spd_policy[POLICY_LEN];
+    FILE * fd_config = NULL;
+    FILE * fd_config_tmp = NULL;
+    memset(spd_policy,0,sizeof(spd_policy));
+
+
+    fd_config_tmp = fopen(setkey_conf_latest, "w+" );
+    if(fd_config_tmp == NULL)
+    {
+	      plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf_latest,errno);
+	      return -1;
+    }
+    chown(setkey_conf_latest,0,1000);
+    if(u_id ==0)
+        snprintf(spd_policy,sizeof(spd_policy),"spdadd %s[%s] %s[%s] %d -P %s ipsec %s/%s//require;\n",src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type,mode);
+    else
+        snprintf(spd_policy,sizeof(spd_policy),"spdadd %s[%s] %s[%s] %d -P %s ipsec %s/%s//unique:%d;\n",src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type,mode,u_id);
+    fwrite( spd_policy, strlen(spd_policy),1,fd_config_tmp );
+    plog_android(LLV_WARNING,"setkey_SP:%s",spd_policy);
+    fclose(fd_config_tmp);
+
+    if(function_setkey(setkey_conf_latest) == 0)
+    {
+        fd_config = fopen(setkey_conf, "a+" );
+        if(fd_config == NULL)
+        {
+	      plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+	      return -1;
+        }
+	chown(setkey_conf,0,1000);
+        fwrite( spd_policy, strlen(spd_policy),1,fd_config );
+        fclose(fd_config);
+    }
+    else
+        return -1;
+    return 0;
+#endif
+	mode = "transport";
+	int ret = setkey_SP_xfrm(XFRM_MSG_NEWPOLICY,src_range,dst_range,protocol,port_src,port_dst,NULL,NULL,ipsec_type,mode,direction,u_id);
+	return ret;
+}
+
+/*set one SP of one direction, just for tunnel mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+  direction:src->dst
+src_tunnel,dst_tunnel: tunnel src ip tunnel dst ip */
+int setkey_SP_tunnel(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type,char * mode, char * direction,int u_id)
+{
+#if 0
+    char spd_policy[POLICY_LEN];
+    FILE * fd_config = NULL;
+    FILE * fd_config_tmp = NULL;
+    memset(spd_policy,0,sizeof(spd_policy));
+
+
+    fd_config_tmp = fopen(setkey_conf_latest, "w+" );
+    if(fd_config_tmp == NULL)
+    {
+	      plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf_latest,errno);
+	      return -1;
+    }
+    chown(setkey_conf_latest,0,1000);
+    if(u_id ==0)
+        snprintf(spd_policy,sizeof(spd_policy),"spdadd %s[%s] %s[%s] %d -P %s ipsec %s/%s/%s-%s/require;\n",src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type,mode,src_tunnel, dst_tunnel);
+    else
+        snprintf(spd_policy,sizeof(spd_policy),"spdadd %s[%s] %s[%s] %d -P %s ipsec %s/%s/%s-%s/unique:%d;\n",src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type,mode,src_tunnel, dst_tunnel,u_id);
+    fwrite( spd_policy, strlen(spd_policy),1,fd_config_tmp );
+    plog_android(LLV_WARNING,"setkey_SP_tunnel:%s",spd_policy);
+    fclose(fd_config_tmp);
+
+    if(function_setkey(setkey_conf_latest) == 0)
+    {
+        fd_config = fopen(setkey_conf, "a+" );
+        if(fd_config == NULL)
+        {
+	      plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+	      return -1;
+        }
+	chown(setkey_conf,0,1000);
+        fwrite( spd_policy, strlen(spd_policy),1,fd_config );
+        fclose(fd_config);
+    }
+    else
+        return -1;
+    return 0;
+#endif
+	mode = "tunnel";
+	int ret = setkey_SP_xfrm(XFRM_MSG_NEWPOLICY,src_range,dst_range,protocol,port_src,port_dst,src_tunnel,dst_tunnel,ipsec_type,mode,direction,u_id);
+	return ret;
+}
+
+/*set one SP of one direction, for 2 layers' ipsec--tunnel mode+transport mode or transport mode+tunnel mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+  direction:src->dst
+src_tunnel,dst_tunnel: tunnel src ip tunnel dst ip */
+int setkey_SP_tunnel_transport(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type1,char * mode1, char * ipsec_type2,char * mode2,char * direction,int u_id1,int u_id2)
+{
+
+    char version[128] = {0};
+    int ret_mapping = 0;
+    property_get("net.ims.ipsec.version",version,"");
+    //plog_android(LLV_WARNING,"getproperty-- net.ims.ipsec.version :%s\n",version);
+    if(strcmp(version,"2.0")==0)
+    {
+	ret_mapping = setkey_SP(src_range,dst_range,protocol,port_src,port_dst,ipsec_type1,mode1, direction,u_id1);
+	return ret_mapping;
+    }
+
+#if 0
+    char spd_policy[POLICY_LEN]={0};
+    char * spd_policy_mode1= (char *)malloc(POLICY_MODE);
+
+    FILE * fd_config = NULL;
+    FILE * fd_config_tmp = NULL;
+
+
+    if(spd_policy_mode1==NULL)
+    {
+	      plog_android(LLV_WARNING,"malloc spd_policy_mode1 failed,errno:%d",errno);
+	      return -1;
+    }
+    memset(spd_policy_mode1,0,POLICY_MODE);
+
+    char * spd_policy_mode2= (char *)malloc(POLICY_MODE);
+    if(spd_policy_mode2==NULL)
+    {
+	      plog_android(LLV_WARNING,"malloc spd_policy_mode2 failed,errno:%d",errno);
+	      if(spd_policy_mode1)
+			free(spd_policy_mode1);
+	      return -1;
+    }
+    memset(spd_policy_mode2,0,POLICY_MODE);
+
+    fd_config_tmp = fopen(setkey_conf_latest, "w+" );
+    if(fd_config_tmp == NULL)
+    {
+	      plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf_latest,errno);
+	      if(spd_policy_mode1)
+			free(spd_policy_mode1);
+	      if(spd_policy_mode2)
+			free(spd_policy_mode2);
+	      return -1;
+    }
+    chown(setkey_conf_latest,0,1000);
+    if(u_id1 ==0)
+        if(strcmp(mode1,"transport")==0)
+        	snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s//require",ipsec_type1,mode1);
+	else
+		snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s/%s-%s/require",ipsec_type1,mode1,src_tunnel,dst_tunnel);
+    else
+        if(strcmp(mode1,"transport")==0)
+        	snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s//unique:%d",ipsec_type1,mode1,u_id1);
+	else
+		snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s/%s-%s/unique:%d",ipsec_type1,mode1,src_tunnel,dst_tunnel,u_id1);
+    if(u_id2 ==0)
+        if(strcmp(mode2,"transport")==0)
+        	snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s//require;\n",ipsec_type2,mode2);
+	else
+		snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s/%s-%s/require;\n",ipsec_type2,mode2,src_tunnel,dst_tunnel);
+    else
+        if(strcmp(mode2,"transport")==0)
+        	snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s//unique:%d;\n",ipsec_type2,mode2,u_id2);
+	else
+		snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s/%s-%s/unique:%d;\n",ipsec_type2,mode2,src_tunnel,dst_tunnel,u_id2);
+
+    snprintf(spd_policy,sizeof(spd_policy),"spdadd %s[%s] %s[%s] %d -P %s prio 2147482648 ipsec %s %s",src_range,port_src,dst_range,port_dst,protocol,direction,spd_policy_mode1,spd_policy_mode2);
+    fwrite( spd_policy, strlen(spd_policy),1,fd_config_tmp );
+    plog_android(LLV_WARNING,"setkey_SP_tunnel_transport:%s",spd_policy);
+    fclose(fd_config_tmp);
+    if(spd_policy_mode1)
+	free(spd_policy_mode1);
+    if(spd_policy_mode2)
+	free(spd_policy_mode2);
+    if(function_setkey(setkey_conf_latest) == 0)
+    {
+        fd_config = fopen(setkey_conf, "a+" );
+        if(fd_config == NULL)
+        {
+	      plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+	      return -1;
+        }
+	chown(setkey_conf,0,1000);
+        fwrite( spd_policy, strlen(spd_policy),1,fd_config );
+        fclose(fd_config);
+    }
+    else
+        return -1;
+    return 0;
+#endif
+	int ret = setkey_SP_2layer_xfrm(XFRM_MSG_UPDPOLICY,src_range,dst_range,protocol,port_src,port_dst,src_tunnel,dst_tunnel,ipsec_type1,mode1,ipsec_type2,mode2,direction,u_id1,u_id2);
+	return ret;
+}
+
+
+/*update one SP of one direction, just for transport mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+  direction:src->dst*/
+int setkey_SP_update_transport(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * ipsec_type, char * direction,int u_id)
+{
+#if 0
+    char spd_policy[POLICY_LEN];
+    FILE * fd_config = NULL;
+    FILE * fd_config_tmp = NULL;
+    memset(spd_policy,0,sizeof(spd_policy));
+
+
+    fd_config_tmp = fopen(setkey_conf_latest, "w+" );
+    if(fd_config_tmp == NULL)
+    {
+	      plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf_latest,errno);
+	      return -1;
+    }
+    chown(setkey_conf_latest,0,1000);
+    if(u_id ==0)
+        snprintf(spd_policy,sizeof(spd_policy),"spdupdate %s[%s] %s[%s] %d -P %s ipsec %s/transport//require;\n",src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type);
+    else
+        snprintf(spd_policy,sizeof(spd_policy),"spdupdate %s[%s] %s[%s] %d -P %s ipsec %s/transport//unique:%d;\n",src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type,u_id);
+    fwrite( spd_policy, strlen(spd_policy),1,fd_config_tmp );
+    plog_android(LLV_WARNING,"setkey_SP_update_transport:%s",spd_policy);
+    fclose(fd_config_tmp);
+
+    if(function_setkey(setkey_conf_latest) == 0)
+    {
+        fd_config = fopen(setkey_conf, "a+" );
+        if(fd_config == NULL)
+        {
+	      plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+	      return -1;
+        }
+	chown(setkey_conf,0,1000);
+        fwrite( spd_policy, strlen(spd_policy),1,fd_config );
+        fclose(fd_config);
+    }
+    else
+        return -1;
+    return 0;
+#endif
+	int ret = setkey_SP_xfrm(XFRM_MSG_UPDPOLICY,src_range,dst_range,protocol,port_src,port_dst,NULL,NULL,ipsec_type,"transport",direction,u_id);
+	return ret;
+}
+
+/*update one SP of one direction, for 2 layers' ipsec--tunnel mode+transport mode or transport mode+tunnel mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+  direction:src->dst
+src_tunnel,dst_tunnel: tunnel src ip tunnel dst ip */
+int setkey_SP_update_tunnel_transport(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type1,char * mode1, char * ipsec_type2,char * mode2,char * direction,int u_id1,int u_id2)
+{
+#if 0
+    char spd_policy[POLICY_LEN]={0};
+    char * spd_policy_mode1= (char *)malloc(POLICY_MODE);
+    FILE * fd_config = NULL;
+    FILE * fd_config_tmp = NULL;
+
+
+    if(spd_policy_mode1==NULL)
+    {
+	      plog_android(LLV_WARNING,"malloc spd_policy_mode1 failed,errno:%d",errno);
+	      return -1;
+    }
+    memset(spd_policy_mode1,0,POLICY_MODE);
+    char * spd_policy_mode2= (char *)malloc(POLICY_MODE);
+    if(spd_policy_mode2==NULL)
+    {
+	      plog_android(LLV_WARNING,"malloc spd_policy_mode2 failed,errno:%d",errno);
+	      if(spd_policy_mode1)
+					free(spd_policy_mode1);
+	      return -1;
+    }
+    memset(spd_policy_mode2,0,POLICY_MODE);
+
+    fd_config_tmp = fopen(setkey_conf_latest, "w+" );
+    if(fd_config_tmp == NULL)
+    {
+	      plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf_latest,errno);
+	      if(spd_policy_mode1)
+			free(spd_policy_mode1);
+	      if(spd_policy_mode2)
+			free(spd_policy_mode2);
+	      return -1;
+    }
+    chown(setkey_conf_latest,0,1000);
+    if(u_id1 ==0)
+        if(strcmp(mode1,"transport")==0)
+        	snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s//require",ipsec_type1,mode1);
+	else
+		snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s/%s-%s/require",ipsec_type1,mode1,src_tunnel,dst_tunnel);
+    else
+        if(strcmp(mode1,"transport")==0)
+        	snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s//unique:%d",ipsec_type1,mode1,u_id1);
+	else
+		snprintf(spd_policy_mode1,POLICY_MODE,"%s/%s/%s-%s/unique:%d",ipsec_type1,mode1,src_tunnel,dst_tunnel,u_id1);
+    if(u_id2 ==0)
+        if(strcmp(mode2,"transport")==0)
+        	snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s//require;\n",ipsec_type2,mode2);
+	else
+		snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s/%s-%s/require;\n",ipsec_type2,mode2,src_tunnel,dst_tunnel);
+    else
+        if(strcmp(mode2,"transport")==0)
+        	snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s//unique:%d;\n",ipsec_type2,mode2,u_id2);
+	else
+		snprintf(spd_policy_mode2,POLICY_MODE,"%s/%s/%s-%s/unique:%d;\n",ipsec_type2,mode2,src_tunnel,dst_tunnel,u_id2);
+
+    snprintf(spd_policy,sizeof(spd_policy),"spdupdate %s[%s] %s[%s] %d -P %s prio 2147482648 ipsec %s %s",src_range,port_src,dst_range,port_dst,protocol,direction,spd_policy_mode1,spd_policy_mode2);
+    fwrite( spd_policy, strlen(spd_policy),1,fd_config_tmp );
+    plog_android(LLV_WARNING,"setkey_SP_update_tunnel_transport:%s",spd_policy);
+    fclose(fd_config_tmp);
+    if(spd_policy_mode1)
+	free(spd_policy_mode1);
+    if(spd_policy_mode2)
+	free(spd_policy_mode2);
+    if(function_setkey(setkey_conf_latest) == 0)
+    {
+        fd_config = fopen(setkey_conf, "a+" );
+        if(fd_config == NULL)
+        {
+	      plog_android(LLV_WARNING,"open %s failed,errno:%d",setkey_conf,errno);
+	      return -1;
+        }
+	chown(setkey_conf,0,1000);
+        fwrite( spd_policy, strlen(spd_policy),1,fd_config );
+        fclose(fd_config);
+    }
+    else
+        return -1;
+    return 0;
+#endif
+	int ret = setkey_SP_2layer_xfrm(XFRM_MSG_UPDPOLICY,src_range,dst_range,protocol,port_src,port_dst,src_tunnel,dst_tunnel,ipsec_type1,mode1,ipsec_type2,mode2,direction,u_id1,u_id2);
+	return ret;
+}
+
+
+/*flush SA\SP from setkey.conf*/
+int flush_SA_SP_exist()
+{
+#if 0
+	FILE *fpSrc = NULL;
+	FILE *fpDst = NULL;
+    char * p_add = NULL;
+    char * p_spdadd = NULL;
+    char * p = NULL;
+    char * sp = NULL;
+    char * sp_ipsec = NULL;
+    char * sp_prio = NULL;
+#if 0
+    char * sp_tmp = NULL;
+    char * sp_src_tmp = NULL;
+    char * sp_dst_tmp = NULL;
+    char * sp_dst = NULL;
+#endif
+    if(access(setkey_conf,0) != 0)
+    {
+	    plog_android(LLV_WARNING,"There is no SA before\n");
+	    return 0;
+    }
+
+
+	char  * achBuf = (char *)malloc(POLICY_LEN);
+    if(achBuf == NULL)
+	{
+		plog_android(LLV_WARNING,"malloc achBuf failed\n");
+		return -1;
+	}
+ 	char * achBuf_deletmp = (char *)malloc(POLICY_LEN);
+    if(achBuf_deletmp == NULL)
+	{
+		plog_android(LLV_WARNING,"malloc achBuf_deletmp failed\n");
+		if(achBuf)
+			free(achBuf);
+
+		return -1;
+	}
+ 	char * achBuf_delet = (char *)malloc(POLICY_LEN);
+    if(achBuf_delet == NULL)
+	{
+		plog_android(LLV_WARNING,"malloc achBuf_delet failed\n");
+		if(achBuf)
+			free(achBuf);
+		if(achBuf_deletmp)
+			free(achBuf_deletmp);
+		return -1;
+	}
+
+
+	fpSrc = fopen(setkey_conf, "rt");
+	if (NULL == fpSrc)
+	{
+		plog_android(LLV_WARNING, "can't open %s,errno:%d",setkey_conf,errno);
+		if(achBuf)
+			free(achBuf);
+		if(achBuf_deletmp)
+			free(achBuf_deletmp);
+		if(achBuf_delet)
+			free(achBuf_delet);
+		return -1;
+	}
+	chown(setkey_conf,0,1000);
+	fpDst = fopen(setkey_conf_latest, "w+");
+	if (NULL== fpDst)
+	{
+		if(achBuf)
+			free(achBuf);
+		if(achBuf_deletmp)
+			free(achBuf_deletmp);
+		if(achBuf_delet)
+			free(achBuf_delet);
+		plog_android(LLV_WARNING,"Create source file: %s failed,errno:%d\n", setkey_conf_bak,errno);
+		if(fpSrc)
+			fclose(fpSrc);
+		return -1;
+	}
+	chown(setkey_conf_latest,0,1000);
+    fseek(fpSrc,0L,SEEK_SET);
+	while (!feof(fpSrc))
+	{
+		memset(achBuf, 0, POLICY_LEN);
+		memset(achBuf_deletmp, 0, POLICY_LEN);
+		memset(achBuf_delet, 0, POLICY_LEN);
+		fgets(achBuf, POLICY_LEN, fpSrc);
+
+ 		if (((p_add = strstr(achBuf, "add")) != NULL)&&(strstr(achBuf, "spdadd") == NULL) )
+		{
+
+			p = strstr(p_add,"-m");
+			if(p!= NULL)
+			{
+				memcpy(achBuf_deletmp,p_add + strlen("add"),p-p_add-strlen("add"));
+				snprintf(achBuf_delet,POLICY_LEN-1,"delete %s;\n",achBuf_deletmp) ;
+               			plog_android(LLV_WARNING,"delete SA:%s\n", achBuf_delet);
+			    	fputs(achBuf_delet, fpDst);
+			}
+			else
+			{
+				plog_android(LLV_WARNING,"There are some cmd error in %s,then flush all SAs and SPs\n", setkey_conf);
+                		setkey_flushSAD();
+                		setkey_flushSPD();
+				if(achBuf)
+					free(achBuf);
+				if(achBuf_deletmp)
+					free(achBuf_deletmp);
+				if(achBuf_delet)
+					free(achBuf_delet);
+				if(fpSrc)
+					fclose(fpSrc);
+				if(fpDst)
+					fclose(fpDst);
+				return -1;
+			}
+		}
+
+		if((p_spdadd = strstr(achBuf, "spdadd")) != NULL)
+		{
+			sp = p_spdadd+strlen("spdadd");
+            		if((sp_prio =strstr(sp,"prio"))!=NULL)
+            		{
+		        memset(achBuf_deletmp, 0, POLICY_LEN);
+		        memset(achBuf_delet, 0, POLICY_LEN);
+		        strncpy(achBuf_deletmp,sp,sp_prio-sp);
+			snprintf(achBuf_delet,POLICY_LEN-1,"spddelete %s",achBuf_deletmp);
+                	strcat(achBuf_delet,";\n");
+		        fputs(achBuf_delet, fpDst);
+               		plog_android(LLV_WARNING,"delete policy: %s\n", achBuf_delet);
+           	 	}
+			else if((sp_ipsec =strstr(sp,"ipsec"))!=NULL)
+            		{
+		        memset(achBuf_deletmp, 0, POLICY_LEN);
+		        memset(achBuf_delet, 0, POLICY_LEN);
+		        strncpy(achBuf_deletmp,sp,sp_ipsec-sp);
+			    snprintf(achBuf_delet,POLICY_LEN-1,"spddelete %s",achBuf_deletmp);
+                strcat(achBuf_delet,";\n");
+		        fputs(achBuf_delet, fpDst);
+                plog_android(LLV_WARNING,"delete policy: %s\n", achBuf_delet);
+            }
+			else
+			{
+		        plog_android(LLV_WARNING,"There are some cmd error in %s,no ,then flush all SAs and SPs\n", setkey_conf);
+                	setkey_flushSAD();
+                	setkey_flushSPD();
+			if(achBuf)
+				free(achBuf);
+			if(achBuf_deletmp)
+				free(achBuf_deletmp);
+			if(achBuf_delet)
+				free(achBuf_delet);
+			if(fpSrc)
+				fclose(fpSrc);
+			if(fpDst)
+				fclose(fpDst);
+		        return -1;
+			}
+#if 0
+			if((sp_tmp =strchr(sp,'['))!=NULL)
+			{
+		        memset(achBuf_deletmp, 0, POLICY_LEN);
+		        memset(achBuf_delet, 0, POLICY_LEN);
+				strncpy(achBuf_deletmp,sp,sp_tmp-sp);
+				snprintf(achBuf_delet,POLICY_LEN-1,"spddelete %s",achBuf_deletmp);
+                plog_android(LLV_WARNING,"src[ achBuf_delet: %s,sp_tmp:%s\n", achBuf_deletmp,sp_tmp);
+			    if((sp_src_tmp =strchr(sp_tmp,']'))!=NULL)
+			    {
+
+			    	if((sp_dst_tmp =strchr(sp_src_tmp,'['))!=NULL)
+			    	{
+			    		memset(achBuf_deletmp, 0, POLICY_LEN);
+			    		strncpy(achBuf_deletmp,sp_src_tmp+strlen("]"),sp_dst_tmp-sp_src_tmp-strlen("]"));
+				        strcat(achBuf_delet,achBuf_deletmp);
+                        plog_android(LLV_WARNING,"src]_achBuf_delet: %s,achBuf:%s,sp_dst_tmp:%s\n", achBuf_deletmp,achBuf,sp_dst_tmp);
+				        if((sp_dst =strchr(sp_dst_tmp,']'))!=NULL)
+				        {
+				        	if((sp_ipsec =strstr(sp_dst,"ipsec"))!=NULL)
+				        	{
+			    		        memset(achBuf_deletmp, 0, POLICY_LEN);
+			    		        strncpy(achBuf_deletmp,sp_dst+strlen("]"),sp_ipsec-sp_dst-strlen("]"));
+				                strcat(achBuf_delet,achBuf_deletmp);
+                                strcat(achBuf_delet,";\n");
+				                fputs(achBuf_delet, fpDst);
+                                plog_android(LLV_WARNING,"spdadd :%s\n",achBuf_delet);
+				            }
+				            else
+				            {
+				            	plog_android(LLV_WARNING,"There are some cmd error in %s,before ipsec,then flush all SAs and SPs\n", setkey_conf);
+                                setkey_flushSAD();
+                                setkey_flushSPD();
+				            	return -1;
+				            }
+				        }
+				        else
+			            {
+				            plog_android(LLV_WARNING,"There are some cmd error in %s,no dst],then flush all SAs and SPs\n", setkey_conf);
+                            setkey_flushSAD();
+                            setkey_flushSPD();
+				            return -1;
+			            }
+			    	}
+			        else
+			        {
+				        plog_android(LLV_WARNING,"There are some cmd error in %s,no dst[,then flush all SAs and SPs\n", setkey_conf);
+                                        setkey_flushSAD();
+                                        setkey_flushSPD();
+				        return -1;
+			        }
+			    }
+			    else
+			    {
+				    plog_android(LLV_WARNING,"There are some cmd error in %s,no ],then flush all SAs and SPs\n", setkey_conf);
+                    setkey_flushSAD();
+                    setkey_flushSPD();
+				    return -1;
+			    }
+
+			}
+			else
+			{
+				plog_android(LLV_WARNING,"There are some cmd error in %s,no [,then flush all SAs and SPs\n", setkey_conf);
+                setkey_flushSAD();
+                setkey_flushSPD();
+				return -1;
+			}
+#endif
+		}
+
+
+	}
+	fclose(fpSrc);
+	fclose(fpDst);
+	if(achBuf)
+		free(achBuf);
+	if(achBuf_deletmp)
+		free(achBuf_deletmp);
+	if(achBuf_delet)
+		free(achBuf_delet);
+    if(function_setkey(setkey_conf_latest) == -1)
+    {
+        return -1;
+    }
+    else
+    {
+    	if(shell_rm() == -1)
+        {
+	        return -1;
+        }
+    }
+	return 0;
+#endif
+	int ret = flush_SA_SP_exist_xfrm();
+	return ret;
+}
+
+
+
+
diff --git a/src/connectivity/libipsecims/setkey_fileio.h b/src/connectivity/libipsecims/setkey_fileio.h
new file mode 100644
index 0000000..141ecb3
--- /dev/null
+++ b/src/connectivity/libipsecims/setkey_fileio.h
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include "utils_xfrm.h"
+
+
+/*flush all SA*/
+extern int setkey_flushSAD(void);
+extern int setkey_flushSAD_xfrm(char * ipsec_type);
+/*flush all SP*/
+extern int setkey_flushSPD(void);
+extern int setkey_flushSPD_xfrm(void);
+/*delete one SA entry*/
+extern int setkey_deleteSA(char * src,char * dst,char * ipsec_type,char * spi_src);
+extern int setkey_deleteSA_xfrm(char * src,char * dst,char * ipsec_type,char * spi_src);
+
+/*delete one SP entry*/
+int setkey_deleteSP(char * src,char * dst,enum PROTOCOL_TYPE protocol,char * src_port,char * dst_port,char * direction);
+int setkey_deleteSP_xfrm(char * src,char * dst,enum PROTOCOL_TYPE protocol,char * src_port,char * dst_port,char * direction);
+
+/*dump all SA */
+extern int dump_setkeySA(void);
+
+/*dump all SP */
+extern int dump_setkeySP(void);
+
+/*set one SA*/
+/*ipsec_type:ah esp
+  mode:transport tunnel
+  encrp_algo_src:encryption algorithm,des-cbc,3des-cbc...
+  encrp_algo_src:key of encryption algorithm
+  intergrity_algo_src:authentication algorithm ,hmac-md5,hmac-sha1
+  intergrity_key_src:key of authentication algorithm
+*/
+extern int setkey_setSA(char * ip_src,char * ip_dst,char * ipsec_type,char * spi_src,char * mode, char * encrp_algo_src,char * encrp_key_src,char * intergrity_algo_src,char * intergrity_key_src,int u_id);
+extern int setkey_setSA_xfrm(int cmd,char * ip_src,char * ip_dst,char * ipsec_type,char * spi_src,char * mode, char * encrp_algo_src,char * encrp_key_src,char * intergrity_algo_src,char * intergrity_key_src,int u_id);
+
+extern int setkey_setSA_update(char * ip_src,char * ip_dst,char * ipsec_type,char * spi_src,char * mode,
+                 char * encrp_algo_src,char * encrp_key_src,char * intergrity_algo_src,char * intergrity_key_src,int u_id);
+
+/*set one SP of one direction just for transport mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+  direction:src->dst */
+extern int setkey_SP(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * ipsec_type,char * mode, char * direction,int u_id);
+extern int setkey_SP_xfrm(int cmd,char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type,char * mode, char * direction,int u_id);
+
+/*set one SP of one direction, just for tunnel mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+  direction:src->dst
+src_tunnel,dst_tunnel: tunnel src ip tunnel dst ip */
+extern int setkey_SP_tunnel(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type,char * mode, char * direction,int u_id);
+
+
+/*set one SP of one direction, for 2 layers' ipsec--tunnel mode+transport mode or transport mode+tunnel mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+  direction:src->dst
+src_tunnel,dst_tunnel: tunnel src ip tunnel dst ip */
+extern int setkey_SP_tunnel_transport(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type1,char * mode1, char * ipsec_type2,char * mode2,char * direction,int u_id1,int u_id2);
+
+/*update one SP of one direction, just for transport mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+  direction:src->dst*/
+int setkey_SP_update_transport(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * ipsec_type, char * direction,int u_id);
+
+
+/*update one SP of one direction, for 2 layers' ipsec--tunnel mode+transport mode or transport mode+tunnel mode*/
+/*protocol:tcp icmp udp icmp6 ip4 gre
+  direction:src->dst
+src_tunnel,dst_tunnel: tunnel src ip tunnel dst ip */
+int setkey_SP_update_tunnel_transport(char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type1,char * mode1, char * ipsec_type2,char * mode2,char * direction,int u_id1,int u_id2);
+int setkey_SP_2layer_xfrm(int cmd,char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type1,char * mode1, char * ipsec_type2,char * mode2,char * direction,int u_id1,int u_id2);
+
+/*flush SA\SP from setkey.conf*/
+extern int flush_SA_SP_exist();
+extern int flush_SA_SP_exist_xfrm();
+
diff --git a/src/connectivity/libipsecims/setkey_xfrm.c b/src/connectivity/libipsecims/setkey_xfrm.c
new file mode 100644
index 0000000..c2cffba
--- /dev/null
+++ b/src/connectivity/libipsecims/setkey_xfrm.c
@@ -0,0 +1,833 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include <linux/capability.h>
+#include <sys/capability.h>
+#include <cutils/properties.h>
+#include "setkey_fileio.h"
+#include "setkey_xfrm_parse.h"
+#include "utils_xfrm.h"
+#define LOG_TAG "setkey"
+#include <log/log.h>
+#include <cutils/log.h>
+
+int volte_pid = -1;
+extern program_invocation_name;
+/*only record volte_stack's pid for flush_SA_SP_exist's use*/
+void set_property_volte()
+{
+	char pid[8] ={0};
+	if(program_invocation_name!=NULL)
+	{
+		ALOGE("program_invocation_name:%s\n",program_invocation_name);
+	}
+	if(strstr(program_invocation_name,"volte")!= NULL)
+		if(volte_pid ==-1)
+		{
+			sprintf(pid,"%d",getpid());
+			int ret = property_set("net.ims.volte.pid",pid);
+  			if(ret != 0)
+  			{
+      				ALOGE("set property failed,errno:%d\n",errno);
+				return;
+  			}
+			volte_pid =getpid();
+		}
+}
+
+static int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
+	      int alen)
+{
+	int len = RTA_LENGTH(alen);
+	struct rtattr *rta = NULL;
+
+	if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
+		ALOGD( "addattr_l ERROR: message exceeded bound of %d\n",maxlen);
+		return -1;
+	}
+
+	rta = NLMSG_TAIL(n);
+	rta->rta_type = type;
+	rta->rta_len = len;
+	memcpy(RTA_DATA(rta), data, alen);
+	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
+	return 0;
+}
+
+int setkey_deleteSP_xfrm(char * src,char * dst,enum PROTOCOL_TYPE protocol,char * src_port,char * dst_port,char * direction)
+{
+
+	char src_arr[128] = {0};
+	char dst_arr[128] = {0};
+	unsigned groups = ~((unsigned)0); /* XXX */
+	struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+
+	memcpy(src_arr,src,strlen(src));
+	memcpy(dst_arr,dst,strlen(dst));
+
+
+/*fragment delete policy netlink msg*/
+	struct {
+		struct nlmsghdr			n;
+		struct xfrm_userpolicy_id	xpid;
+		char				buf[RTA_BUF_SIZE];
+	} req;
+
+	memset(&req, 0, sizeof(req));
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpid));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = XFRM_MSG_DELPOLICY;
+
+	req.xpid.dir = xfrm_dir_parse(direction);
+	if(req.xpid.dir == XFRM_POLICY_ERROR)
+	{
+		ALOGD("setkey_deleteSP_xfrm dir:%s is wrong\n",direction);
+		return -1;
+	}
+	xfrm_selector_parse(&req.xpid.sel, src_arr,dst_arr,protocol,src_port,dst_port);
+
+	groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+	if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+		return -1;
+
+	if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+	{
+		ALOGD("set2layeripsecrules_xfrm send failed,errno:%d\n",errno);
+		rtnl_close_xfrm(&rth);
+		return -1;
+	}
+	if(req.xpid.dir ==XFRM_POLICY_IN)
+	{
+		req.xpid.dir = XFRM_POLICY_FWD;
+		if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+		{
+			ALOGD("setkey_deleteSP_xfrm send POLICY_FWD failed,errno:%d",errno);
+			rtnl_close_xfrm(&rth);
+			return -1;
+		}
+	}
+#ifdef INIT_ENG_BUILD
+	ALOGD("setkey_deleteSP_xfrm successed fd:%d --spddelete %s[%s] %s[%s] %d -P %s;\n",rth.fd,src,src_port,dst,dst_port,protocol,direction);
+#endif
+	rtnl_close_xfrm(&rth);
+	return 0;
+}
+
+int setkey_deleteSA_xfrm(char * src,char * dst,char * ipsec_type,char * spi_src)
+{
+
+	char src_arr[128] = {0};
+	char dst_arr[128] = {0};
+	unsigned groups = ~((unsigned)0); /* XXX */
+	struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+	memcpy(src_arr,src,strlen(src));
+	memcpy(dst_arr,dst,strlen(dst));
+
+	/*fragment delete state netlink msg*/
+	struct {
+		struct nlmsghdr 	n;
+		struct xfrm_usersa_id	xsid;
+		char   			buf[RTA_BUF_SIZE];
+	} req;
+
+	memset(&req, 0, sizeof(req));
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsid));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = XFRM_MSG_DELSA;
+	req.xsid.family = AF_UNSPEC;
+
+	/* ID */
+	struct xfrm_id id ;
+	xfrm_address_t saddr_xfrm;
+	memset(&id, 0, sizeof(id));
+	memset(&saddr_xfrm, 0, sizeof(saddr_xfrm));
+	xfrm_id_parse(&saddr_xfrm, &id, &req.xsid.family,src_arr,dst_arr,ipsec_type);
+	__u32 spi;
+	if (get_u32(&spi, spi_src, 0))
+	{
+		ALOGD("xfrm_id_parse spi:%s is wrong\n",spi_src);
+		return -1;
+	}
+
+	spi = htonl(spi);
+	id.spi = spi;
+	memcpy(&req.xsid.daddr, &id.daddr, sizeof(req.xsid.daddr));
+	req.xsid.spi = id.spi;
+	req.xsid.proto = id.proto;
+
+	addattr_l(&req.n, sizeof(req.buf), XFRMA_SRCADDR,
+				  (void *)&saddr_xfrm, sizeof(saddr_xfrm));
+
+	groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+	if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+		return -1;
+	if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+	{
+		ALOGD("set2layeripsecrules_xfrm send failed,errno:%d\n",errno);
+		rtnl_close_xfrm(&rth);
+		return -1;
+	}
+#ifdef INIT_ENG_BUILD
+	ALOGD("setkey_deleteSA_xfrm successed fd:%d --delete %s %s %s %s;\n",rth.fd,src,dst,ipsec_type,spi_src);
+#endif
+	rtnl_close_xfrm(&rth);
+	return 0;
+}
+
+int setkey_setSA_xfrm(int cmd,char * ip_src,char * ip_dst,char * ipsec_type,char * spi_src,char * mode,
+                 char * encrp_algo_src,char * encrp_key_src,char * intergrity_algo_src,char * intergrity_key_src,int u_id)
+{
+
+	char encrp_algo_arr[128] = {0};
+	char intergrity_algo_arr[128] = {0};
+	char srcport_arr[64] = {0};
+	char dstport_arr[64] = {0};
+	char * port_head = NULL;
+	char * port_tail = NULL;
+	char src_arr[128] = {0};
+	char dst_arr[128] = {0};
+	unsigned groups = ~((unsigned)0); /* XXX */
+	struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+	set_property_volte();
+
+	/*sepearte src addr and src port\dst addr and dst port, state's format often is add xx[xx] xx[xx] esp xx ....*/
+	port_head = strchr(ip_src,'[');
+	if(port_head == NULL)
+	{
+		memcpy(src_arr,ip_src,strlen(ip_src));
+		memcpy(srcport_arr,"0",1);
+	}
+	else
+	{
+		port_tail = strchr(ip_src,']');
+		if (port_tail == NULL)
+		{
+#ifdef INIT_ENG_BUILD
+			ALOGD("setkey_SA_xfrm wrong src ip:%s \n",ip_src);
+#endif
+			return -1;
+		}
+		else
+		{
+			memcpy(srcport_arr,port_head+1,port_tail-port_head-1);
+			memcpy(src_arr,ip_src,port_head-ip_src);
+		}
+	}
+	port_head = strchr(ip_dst,'[');
+	if(port_head==NULL)
+	{
+		memcpy(dst_arr,ip_dst,strlen(ip_dst));
+		memcpy(dstport_arr,"0",1);
+	}
+	else
+	{
+		port_tail = strchr(ip_dst,']');
+		if (port_tail == NULL)
+		{
+#ifdef INIT_ENG_BUILD
+			ALOGD("setkey_SA_xfrm wrong dst ip:%s \n",ip_dst);
+#endif
+			return -1;
+		}
+		else
+		{
+			memcpy(dstport_arr,port_head+1,port_tail-port_head-1);
+			memcpy(dst_arr,ip_dst,port_head-ip_dst);
+		}
+	}
+
+	/*fragment add/modify state netlink msg*/
+	struct {
+		struct nlmsghdr 	n;
+		struct xfrm_usersa_info xsinfo;
+		char   			buf[RTA_BUF_SIZE];
+	} req;
+
+	memset(&req, 0, sizeof(req));
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsinfo));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = cmd;
+
+
+	req.xsinfo.family = AF_UNSPEC;
+	req.xsinfo.lft.soft_byte_limit = XFRM_INF;
+	req.xsinfo.lft.hard_byte_limit = XFRM_INF;
+	req.xsinfo.lft.soft_packet_limit = XFRM_INF;
+	req.xsinfo.lft.hard_packet_limit = XFRM_INF;
+	req.xsinfo.reqid = u_id;
+	/* ID */
+	if(xfrm_mode_parse(&req.xsinfo.mode, mode) ==-1)
+	{
+		ALOGD("setkey_SA_xfrm mode:%s is wrong\n",mode);
+		return -1;
+	}
+	__u32 spi;
+	if (get_u32(&spi, spi_src, 0))
+	{
+		ALOGD("xfrm_id_parse spi:%s is wrong\n",spi_src);
+		return -1;
+	}
+
+	spi = htonl(spi);
+	req.xsinfo.id.spi = spi;
+	if(xfrm_id_parse(&req.xsinfo.saddr, &req.xsinfo.id,&req.xsinfo.family,
+				      src_arr,dst_arr,ipsec_type)<0)
+	{
+#ifdef INIT_ENG_BUILD
+		ALOGD("setkey_SA_xfrm->xfrm_id_parse failed ip_src:%s,ip_dst:%s,ipsec_type:%s",ip_src,ip_dst,ipsec_type);
+#endif
+		return -1;
+	}
+	xfrm_selector_parse(&req.xsinfo.sel, src_arr,dst_arr,0,srcport_arr,dstport_arr);
+	/* ALGO */
+	struct {
+		union {
+			struct xfrm_algo alg;
+			struct xfrm_algo_aead aead;
+			struct xfrm_algo_auth auth;
+		} u;
+		char buf[XFRM_ALGO_KEY_BUF_SIZE];
+	} alg;
+	int len;
+	char *buf = NULL;
+	memset(&alg, 0, sizeof(alg));
+	buf = alg.u.alg.alg_key;
+	len = sizeof(alg.u.alg);
+
+	xfrm_encry_algo_parse(encrp_algo_src, encrp_algo_arr);
+	if(strcmp(encrp_algo_arr,"not-supported") == 0)
+		return -1;
+
+	if((encrp_algo_src == NULL)||(strcmp(encrp_algo_src,"null")==0))
+	{
+			alg.u.alg.alg_key_len = 0;
+			memcpy(alg.u.alg.alg_name, "ecb(cipher_null)", strlen("ecb(cipher_null)"));
+	}
+	else
+	if(xfrm_algo_parse((void *)&alg,  encrp_algo_arr, encrp_key_src,
+			   buf, sizeof(alg.buf))==-1)
+	{
+#ifdef INIT_ENG_BUILD
+		ALOGD("setkey_SA_xfrm->xfrm_algo_parse failed encrp_algo:%s,encrp_key:%s,",encrp_algo_src, encrp_key_src);
+#endif
+		return -1;
+	}
+	len += alg.u.alg.alg_key_len;
+	addattr_l(&req.n, sizeof(req.buf), XFRMA_ALG_CRYPT,(void *)&alg, len);
+
+	memset((void *)&alg, 0,sizeof(alg));
+	buf = alg.u.alg.alg_key;
+	len = sizeof(alg.u.alg);
+	xfrm_interg_algo_parse(intergrity_algo_src, intergrity_algo_arr);
+	if(strcmp(intergrity_algo_arr ,"not-supported") == 0)
+		return -1;
+	if((intergrity_algo_src == NULL)||(strcmp(intergrity_algo_src,"null")==0))
+	{
+			alg.u.alg.alg_key_len = 0;
+			memcpy(alg.u.alg.alg_name, "digest_null", strlen("digest_null"));
+	}
+	else
+	if(xfrm_algo_parse((void *)&alg,  intergrity_algo_arr, intergrity_key_src,
+			   buf, sizeof(alg.buf))<-1)
+	{
+#ifdef INIT_ENG_BUILD
+		ALOGD("setkey_SA_xfrm->xfrm_algo_parse failed intergrity crp_algo:%s,intergrity _key:%s,",intergrity_algo_src, intergrity_key_src);
+#endif
+		return -1;
+	}
+	len += alg.u.alg.alg_key_len;
+	addattr_l(&req.n, sizeof(req.buf), XFRMA_ALG_AUTH,(void *)&alg, len);
+
+	groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+	if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+		return -1;
+
+	if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+	{
+		ALOGD("set2layeripsecrules_xfrm send failed,errno:%d",errno);
+		rtnl_close_xfrm(&rth);
+		return -1;
+	}
+#ifdef INIT_ENG_BUILD
+	ALOGD("setkey_SA_xfrm successed fd:%d ---add %s %s %s %s  -m %s -E %s %s  -A %s %s -u %d; spi:%d\n",rth.fd,ip_src,ip_dst,ipsec_type,spi_src,mode,
+                 encrp_algo_src,encrp_key_src,intergrity_algo_src,intergrity_key_src,u_id,req.xsinfo.id.spi);
+#endif
+	rtnl_close_xfrm(&rth);
+	return 0;
+}
+
+
+int setkey_SP_xfrm(int cmd,char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type,char * mode, char * direction,int u_id)
+{
+	char src_arr[128] = {0};
+	char dst_arr[128] = {0};
+	char src_tunnel_arr[128] = {0};
+	char dst_tunnel_arr[128] = {0};
+	unsigned groups = ~((unsigned)0); /* XXX */
+	struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+	memcpy(src_arr,src_range,strlen(src_range));
+	memcpy(dst_arr,dst_range,strlen(dst_range));
+	if(src_tunnel)
+		memcpy(src_tunnel_arr,src_tunnel,strlen(src_tunnel));
+	if(dst_tunnel)
+		memcpy(dst_tunnel_arr,dst_tunnel,strlen(dst_tunnel));
+
+	set_property_volte();
+
+
+
+	struct req_handle_xfrm req;
+	char tmpls_buf[XFRM_TMPLS_BUF_SIZE];
+	struct xfrm_user_tmpl *tmpl = NULL;
+	int tmpls_len = 0;
+
+
+	memset(&req, 0, sizeof(req));
+	memset(&tmpls_buf, 0, sizeof(tmpls_buf));
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpinfo));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = cmd;
+
+	req.xpinfo.lft.soft_byte_limit = XFRM_INF;
+	req.xpinfo.lft.hard_byte_limit = XFRM_INF;
+	req.xpinfo.lft.soft_packet_limit = XFRM_INF;
+	req.xpinfo.lft.hard_packet_limit = XFRM_INF;
+	req.xpinfo.dir = xfrm_dir_parse(direction);
+	req.xpinfo.priority = 1000;
+	xfrm_selector_parse(&req.xpinfo.sel, src_arr,dst_arr,protocol,port_src,port_dst);
+
+	if(req.xpinfo.dir == XFRM_POLICY_ERROR)
+	{
+		ALOGD("setkey_SP_xfrm dir:%s is wrong",direction);
+		return -1;
+	}
+	tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len);
+
+	if(xfrm_mode_parse(&tmpl->mode, mode) ==-1)
+	{
+		ALOGD("setkey_SP_xfrm mode:%s is wrong",mode);
+		return -1;
+	}
+	tmpl->family = req.xpinfo.sel.family;
+	if(tmpl->mode == XFRM_MODE_TUNNEL)
+	{
+		xfrm_id_parse(&tmpl->saddr, &tmpl->id, &tmpl->family,
+				      src_tunnel_arr,dst_tunnel_arr,ipsec_type);
+	}
+
+	tmpl->aalgos = (~(__u32)0);
+	tmpl->ealgos = (~(__u32)0);
+	tmpl->calgos = (~(__u32)0);
+	tmpl->reqid = u_id;
+	tmpl->id.proto  = xfrm_xfrmproto_getbyname(ipsec_type);
+	if(tmpl->id.proto <0)
+	{
+		ALOGD("setkey_SP_xfrm ipsec_type:%s is wrong",ipsec_type);
+		return -1;
+	}
+	tmpls_len += sizeof(*tmpl);
+	if (tmpls_len > 0) {
+		addattr_l(&req.n, sizeof(req), XFRMA_TMPL,
+			  (void *)tmpls_buf, tmpls_len);
+	}
+
+	groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+	if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+		return -1;
+
+	if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+	{
+		ALOGD("set2layeripsecrules_xfrm send failed,errno:%d",errno);
+		rtnl_close_xfrm(&rth);
+		return -1;
+	}
+	if(req.xpinfo.dir ==XFRM_POLICY_IN)
+	{
+		req.xpinfo.dir = XFRM_POLICY_FWD;
+		if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+		{
+			ALOGD("set2layeripsecrules_xfrm send POLICY_FWD failed,errno:%d",errno);
+			rtnl_close_xfrm(&rth);
+			return -1;
+		}
+	}
+#ifdef INIT_ENG_BUILD
+	ALOGD("setkey_SP_xfrm successed fd:%d --spdadd %s[%s] %s[%s] %d -P %s ipsec %s/%s//unique:%d;\n",rth.fd,src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type,mode,u_id);
+#endif
+	rtnl_close_xfrm(&rth);
+	return 0;
+}
+
+int setkey_SP_2layer_xfrm(int cmd,char * src_range,char * dst_range,enum PROTOCOL_TYPE protocol,char * port_src,char * port_dst,char * src_tunnel,char * dst_tunnel,char * ipsec_type1,char * mode1, char * ipsec_type2,char * mode2,char * direction,int u_id1,int u_id2)
+{
+	char src_arr[128] = {0};
+	char dst_arr[128] = {0};
+	char src_tunnel_arr[128] = {0};
+	char dst_tunnel_arr[128] = {0};
+	unsigned groups = ~((unsigned)0); /* XXX */
+	struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+	memcpy(src_arr,src_range,strlen(src_range));
+	memcpy(dst_arr,dst_range,strlen(dst_range));
+	if(src_tunnel)
+		memcpy(src_tunnel_arr,src_tunnel,strlen(src_tunnel));
+	if(dst_tunnel)
+		memcpy(dst_tunnel_arr,dst_tunnel,strlen(dst_tunnel));
+
+
+	struct req_handle_xfrm req;
+	char tmpls_buf[XFRM_TMPLS_BUF_SIZE];
+	struct xfrm_user_tmpl *tmpl = NULL;
+	int tmpls_len = 0;
+
+	set_property_volte();
+
+	memset(&req, 0, sizeof(req));
+	memset(&tmpls_buf, 0, sizeof(tmpls_buf));
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpinfo));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = cmd;
+
+	req.xpinfo.lft.soft_byte_limit = XFRM_INF;
+	req.xpinfo.lft.hard_byte_limit = XFRM_INF;
+	req.xpinfo.lft.soft_packet_limit = XFRM_INF;
+	req.xpinfo.lft.hard_packet_limit = XFRM_INF;
+	req.xpinfo.dir = xfrm_dir_parse(direction);
+	req.xpinfo.priority = 1000;
+	xfrm_selector_parse(&req.xpinfo.sel, src_arr,dst_arr,protocol,port_src,port_dst);
+
+	if(req.xpinfo.dir == XFRM_POLICY_ERROR)
+	{
+		ALOGD("setkey_SP_xfrm dir:%s is wrong",direction);
+		return -1;
+	}
+	tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len);
+
+	if(xfrm_mode_parse(&tmpl->mode, mode1) ==-1)
+	{
+		ALOGD("setkey_SP_xfrm mode:%s is wrong",mode1);
+		return -1;
+	}
+	tmpl->family = req.xpinfo.sel.family;
+	if(tmpl->mode == XFRM_MODE_TUNNEL)
+	{
+		xfrm_id_parse(&tmpl->saddr, &tmpl->id, &tmpl->family,
+				      src_tunnel_arr,dst_tunnel_arr,ipsec_type1);
+	}
+
+	tmpl->aalgos = (~(__u32)0);
+	tmpl->ealgos = (~(__u32)0);
+	tmpl->calgos = (~(__u32)0);
+	tmpl->reqid = u_id1;
+	tmpl->id.proto  = xfrm_xfrmproto_getbyname(ipsec_type1);
+	if(tmpl->id.proto <0)
+	{
+		ALOGD("setkey_SP_xfrm ipsec_type:%s is wrong",ipsec_type1);
+		return -1;
+	}
+	tmpls_len += sizeof(*tmpl);
+	tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len);
+
+	if(xfrm_mode_parse(&tmpl->mode, mode2) ==-1)
+	{
+		ALOGD("setkey_SP_xfrm mode:%s is wrong",mode1);
+		return -1;
+	}
+	tmpl->family = req.xpinfo.sel.family;
+	if(tmpl->mode == XFRM_MODE_TUNNEL)
+	{
+		xfrm_id_parse(&tmpl->saddr, &tmpl->id, &tmpl->family,
+				      src_tunnel_arr,dst_tunnel_arr,ipsec_type2);
+	}
+	tmpl->aalgos = (~(__u32)0);
+	tmpl->ealgos = (~(__u32)0);
+	tmpl->calgos = (~(__u32)0);
+	tmpl->reqid = u_id2;
+	tmpl->id.proto  = xfrm_xfrmproto_getbyname(ipsec_type2);
+	if(tmpl->id.proto <0)
+	{
+		ALOGD("setkey_SP_xfrm ipsec_type:%s is wrong",ipsec_type2);
+		return -1;
+	}
+	tmpls_len += sizeof(*tmpl);
+	if (tmpls_len > 0) {
+		addattr_l(&req.n, sizeof(req), XFRMA_TMPL,
+			  (void *)tmpls_buf, tmpls_len);
+	}
+
+	groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+	if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+		return -1;
+
+	if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+	{
+		ALOGD("set2layeripsecrules_xfrm send failed,errno:%d",errno);
+		rtnl_close_xfrm(&rth);
+		return -1;
+	}
+	if(req.xpinfo.dir ==XFRM_POLICY_IN)
+	{
+		req.xpinfo.dir = XFRM_POLICY_FWD;
+		if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+		{
+			ALOGD("set2layeripsecrules_xfrm send POLICY_FWD failed,errno:%d",errno);
+			rtnl_close_xfrm(&rth);
+			return -1;
+		}
+	}
+#ifdef INIT_ENG_BUILD
+	ALOGD("setkey_SP_2layer_xfrm successed fd:%d --spdupdate %s[%s] %s[%s] %d -P %s prio 1000 ipsec %s/%s//unique:%d %s/%s/%s-%s/unique:%d;\n",rth.fd,src_range,port_src,dst_range,port_dst,protocol,direction,ipsec_type1,mode1,u_id1,ipsec_type2,mode2,src_tunnel,dst_tunnel,u_id2);
+#endif
+	rtnl_close_xfrm(&rth);
+	return 0;
+}
+int setkey_flushSAD_xfrm(char * ipsec_type)
+{
+	unsigned groups = ~((unsigned)0); /* XXX */
+	struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+	struct {
+		struct nlmsghdr			n;
+		struct xfrm_usersa_flush	xsf;
+	} req;
+
+
+	memset(&req, 0, sizeof(req));
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsf));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = XFRM_MSG_FLUSHSA;
+	req.xsf.proto = 0;
+
+	req.xsf.proto = (__u8)xfrm_xfrmproto_getbyname(ipsec_type);
+	if (req.xsf.proto < 0)
+	{
+		ALOGD("setkey_flushSAD_xfrm :%s is wrong",ipsec_type);
+		return -1;
+	}
+
+	groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+	if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+		return -1;
+
+	if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+	{
+		ALOGD("set2layeripsecrules_xfrm send POLICY_FWD failed,errno:%d",errno);
+		rtnl_close_xfrm(&rth);
+		return -1;
+	}
+	ALOGD("setkey_flushSAD_xfrm successed fd:%d --flush ;\n",rth.fd);
+	rtnl_close_xfrm(&rth);
+
+	return 0;
+}
+int setkey_flushSPD_xfrm(void)
+{
+	unsigned groups = ~((unsigned)0); /* XXX */
+	struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+
+	struct {
+		struct nlmsghdr	n;
+		char		buf[RTA_BUF_SIZE];
+	} req;
+
+	memset(&req, 0, sizeof(req));
+
+
+	req.n.nlmsg_len = NLMSG_LENGTH(0); /* nlmsg data is nothing */
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = XFRM_MSG_FLUSHPOLICY;
+
+	groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+	if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+		return -1;
+	if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+	{
+		ALOGD("set2layeripsecrules_xfrm send POLICY_FWD failed,errno:%d",errno);
+		rtnl_close_xfrm(&rth);
+		return -1;
+	}
+	ALOGD("setkey_flushSPD_xfrm successed fd:%d --flush ;\n",rth.fd);
+
+	rtnl_close_xfrm(&rth);
+
+	return 0;
+}
+int flush_SA_SP_exist_xfrm()
+{
+	unsigned groups = ~((unsigned)0); /* XXX */
+	struct rtnl_handle_xfrm rth = { -1,{0},{0},0,0 };
+
+	struct {
+		struct nlmsghdr nlh;
+		struct rtgenmsg g;
+		__u16 align_rta;	/* attribute has to be 32bit aligned */
+		struct rtattr ext_req;
+		__u32 ext_filter_mask;
+	} req;
+
+	memset(&req, 0, sizeof(req));
+	req.nlh.nlmsg_len = sizeof(req);
+	req.nlh.nlmsg_type = XFRM_MSG_GETPOLICY;
+	req.nlh.nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST;
+	req.nlh.nlmsg_seq = rth.dump = ++rth.seq;
+	req.g.rtgen_family = AF_UNSPEC;
+
+	req.ext_req.rta_type = IFLA_EXT_MASK;
+	req.ext_req.rta_len = RTA_LENGTH(sizeof(__u32));
+	req.ext_filter_mask = RTEXT_FILTER_VF;
+
+	groups |= (nl_mgrp_xfrm(XFRMNLGRP_ACQUIRE)|nl_mgrp_xfrm(XFRMNLGRP_EXPIRE)|nl_mgrp_xfrm(XFRMNLGRP_SA)|nl_mgrp_xfrm(XFRMNLGRP_POLICY));
+
+	if (rtnl_open_byproto_xfrm(&rth, groups, NETLINK_XFRM) < 0)
+		return -1;
+	if(send(rth.fd, (void*)&req, sizeof(req), 0)<0)
+	{
+		ALOGD("flush_SA_SP_exist_xfrm send msg failed,errno:%d",errno);
+		rtnl_close_xfrm(&rth);
+		return -1;
+	}
+	if (rtnl_listen_xfrm(&rth, rtnl_accept_msg_xfrm) < 0)
+	{
+		rtnl_close_xfrm(&rth);
+		ALOGD("flush_SA_SP_exist_xfrm <0 done");
+		return -2;
+	}
+	ALOGD("flush_SA_SP_exist_xfrm done");
+	rtnl_close_xfrm(&rth);
+
+	return 0;
+}
+
+int xfrm_policy_process_delete_exist( struct rtnl_handle_xfrm * rth,struct nlmsghdr *n,pid_t volte_pid)
+{
+
+	struct xfrm_userpolicy_info *xpinfo = NULL;
+	int len = n->nlmsg_len;
+
+
+	xpinfo = NLMSG_DATA(n);
+	len -= NLMSG_SPACE(sizeof(*xpinfo));
+	if (len < 0) {
+		ALOGE( "BUG: wrong nlmsg len %d\n", len);
+		return -1;
+	}
+	if(xpinfo->sel.user != volte_pid)
+	{
+		ALOGE( "we donot need to process:%d's policy\n", xpinfo->sel.user);
+		return 0;
+	}
+
+/*fragment delete policy*/
+	struct {
+		struct nlmsghdr			n;
+		struct xfrm_userpolicy_id	xpid;
+		char				buf[RTA_BUF_SIZE];
+	} req;
+
+	memset(&req, 0, sizeof(req));
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpid));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = XFRM_MSG_DELPOLICY;
+
+	req.xpid.dir = xpinfo->dir;
+
+	memcpy(&req.xpid.sel,&xpinfo->sel,sizeof(req.xpid.sel));
+
+
+	if(send(rth->fd, (void*)&req, sizeof(req), 0)<0)
+	{
+		ALOGD("xfrm_policy_process_delete_exist send failed,errno:%d",errno);
+		return -1;
+	}
+#ifdef INIT_ENG_BUILD
+	if(req.xpid.sel.family == AF_INET)
+		ALOGD("xfrm_policy_process_delete_exist successed fd:%d --spddelete 0x%x[%d] 0x%x[%d] %d -P %d;\n",rth->fd,req.xpid.sel.saddr.a4,req.xpid.sel.sport,req.xpid.sel.daddr.a4,req.xpid.sel.dport,req.xpid.sel.proto,req.xpid.dir);
+        else
+		ALOGD("xfrm_policy_process_delete_exist successed fd:%d --spddelete 0x%x %x %x %x[%d] 0x%x %x %x %x[%d] %d -P %d;\n",rth->fd,
+		req.xpid.sel.saddr.a6[0],req.xpid.sel.saddr.a6[1],req.xpid.sel.saddr.a6[2],req.xpid.sel.saddr.a6[3],req.xpid.sel.sport,
+		req.xpid.sel.daddr.a6[0],req.xpid.sel.daddr.a6[1],req.xpid.sel.daddr.a6[2],req.xpid.sel.daddr.a6[3],req.xpid.sel.dport,
+		req.xpid.sel.proto,req.xpid.dir);
+#endif
+	return 0;
+}
+
+int xfrm_state_process_delete_exist( struct rtnl_handle_xfrm * rth,struct nlmsghdr *n,pid_t volte_pid)
+{
+
+	struct xfrm_usersa_info * xsinfo = NULL;
+	int len = n->nlmsg_len;
+	xfrm_address_t	saddr;
+
+	xsinfo = NLMSG_DATA(n);
+	len -= NLMSG_SPACE(sizeof(*xsinfo));
+	if (len < 0) {
+		ALOGE( "BUG: wrong nlmsg len %d\n", len);
+		return -1;
+	}
+
+	if(xsinfo->sel.user != volte_pid)
+	{
+		ALOGE( "we donot need to process:%d's policy\n", xsinfo->sel.user);
+		return 0;
+	}
+
+/*fragment delete state*/
+	struct {
+		struct nlmsghdr			n;
+		struct xfrm_usersa_id		xsid;
+		char				buf[RTA_BUF_SIZE];
+	} req;
+
+	memset(&req, 0, sizeof(req));
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsid));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = XFRM_MSG_DELSA;
+
+	req.xsid.family = xsinfo->family;
+	memcpy(&req.xsid.daddr,&xsinfo->sel.daddr,sizeof(xsinfo->sel.daddr));
+	memcpy(&saddr,&xsinfo->saddr,sizeof(xsinfo->saddr));
+	addattr_l(&req.n, sizeof(req.buf), XFRMA_SRCADDR,
+				  (void *)&saddr, sizeof(saddr));
+	if(send(rth->fd, (void*)&req, sizeof(req), 0)<0)
+	{
+		ALOGD("xfrm_state_process_delete_exist send failed,errno:%d",errno);
+		return -1;
+	}
+#ifdef INIT_ENG_BUILD
+	if(xsinfo->sel.family == AF_INET)
+		ALOGD("xfrm_state_process_delete_exist successed fd:%d --delete 0x%x 0x%x %d;\n",rth->fd,xsinfo->sel.saddr.a4,xsinfo->sel.daddr.a4,xsinfo->id.spi);
+        else
+		ALOGD("xfrm_state_process_delete_exist successed fd:%d --delete 0x%x %x %x %x 0x%x %x %x %x %d ;\n",rth->fd,
+		xsinfo->sel.saddr.a6[0],xsinfo->sel.saddr.a6[1],xsinfo->sel.saddr.a6[2],xsinfo->sel.saddr.a6[3],
+		xsinfo->sel.daddr.a6[0],xsinfo->sel.daddr.a6[1],xsinfo->sel.daddr.a6[2],xsinfo->sel.daddr.a6[3],
+		xsinfo->id.spi);
+#endif
+	return 0;
+}
+
diff --git a/src/connectivity/libipsecims/setkey_xfrm_parse.c b/src/connectivity/libipsecims/setkey_xfrm_parse.c
new file mode 100644
index 0000000..44e1aeb
--- /dev/null
+++ b/src/connectivity/libipsecims/setkey_xfrm_parse.c
@@ -0,0 +1,272 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include <linux/capability.h>
+#include <sys/capability.h>
+#include <cutils/properties.h>
+#include "setkey_fileio.h"
+#include "utils_xfrm.h"
+#include "setkey_xfrm_parse.h"
+#define LOG_TAG "setkey"
+#include <log/log.h>
+#include <cutils/log.h>
+
+
+const struct typeent xfrmproto_types[]= {
+	{ "esp", IPPROTO_ESP }, { "ah", IPPROTO_AH }, { "comp", IPPROTO_COMP },
+	{ "route2", IPPROTO_ROUTING }, { "hao", IPPROTO_DSTOPTS },
+	{ "ipsec-any", IPSEC_PROTO_ANY },
+	{ NULL, -1 }
+};
+
+
+int xfrm_xfrmproto_getbyname(char *name)
+{
+	int i;
+
+	for (i = 0; ; i++) {
+		const struct typeent *t = &xfrmproto_types[i];
+		if (!t->t_name || t->t_type == -1)
+			break;
+
+		if (strcmp(t->t_name, name) == 0)
+			return t->t_type;
+	}
+
+	return -1;
+}
+
+
+int xfrm_id_parse(xfrm_address_t *saddr_xfrm, struct xfrm_id *id, __u16 *family,
+		 char * src,char * dst,char * ipsec_type)
+{
+
+	inet_prefix dst_prefix;
+	inet_prefix src_prefix;
+
+	memset(&dst_prefix, 0, sizeof(dst_prefix));
+	memset(&src_prefix, 0, sizeof(src_prefix));
+
+	get_prefix(&src_prefix, src, AF_UNSPEC);
+	if (family)
+		*family = src_prefix.family;
+	memcpy(saddr_xfrm, &src_prefix.data, sizeof(*saddr_xfrm));
+	get_prefix(&dst_prefix, dst, AF_UNSPEC);
+	memcpy(&id->daddr, &dst_prefix.data, sizeof(id->daddr));
+
+	int ret = xfrm_xfrmproto_getbyname(ipsec_type);
+	if(ret<0)
+	{
+		ALOGD("xfrm_id_parse %s is wrong\n",ipsec_type);
+		return -1;
+	}
+	id->proto = (__u8)ret;
+
+
+	return 0;
+}
+
+void xfrm_encry_algo_parse(char * encry_src, char *name)
+{
+	if(encry_src == NULL)
+		memcpy(name,"ecb(cipher_null)",strlen("ecb(cipher_null)"));
+	else 	if(strcmp(encry_src,"des-cbc")==0)
+		memcpy(name,"cbc(des)",strlen("cbc(des)"));
+	else 	if(strcmp(encry_src,"des-ede3-cbc")==0)
+		memcpy(name,"cbc(des3_ede)",strlen("cbc(des3_ede)"));
+	else 	if(strcmp(encry_src,"3des-cbc")==0)
+		memcpy(name,"cbc(des3_ede)",strlen("cbc(des3_ede)"));
+	else 	if(strcmp(encry_src,"cast5-cbc")==0)
+		memcpy(name,"cbc(cast5)",strlen("cbc(cast5)"));
+	else 	if(strcmp(encry_src,"blowfish-cbc")==0)
+		memcpy(name,"cbc(blowfish)",strlen("cbc(blowfish)"));
+	else 	if(strcmp(encry_src,"aes-cbc")==0)
+		memcpy(name,"cbc(aes)",strlen("cbc(aes)"));
+	else 	if(strcmp(encry_src,"serpent-cbc")==0)
+		memcpy(name,"cbc(serpent)",strlen("cbc(serpent)"));
+	else 	if(strcmp(encry_src,"camellia-cbc")==0)
+		memcpy(name,"cbc(camellia)",strlen("cbc(camellia)"));
+	else 	if(strcmp(encry_src,"twofish-cbc")==0)
+		memcpy(name,"cbc(twofish)",strlen("cbc(twofish)"));
+	else 	if(strcmp(encry_src,"aes-ctr-rfc3686")==0)
+		memcpy(name,"rfc3686(ctr(aes))",strlen("rfc3686(ctr(aes))"));
+	else    if(strcmp(encry_src,"null")==0)
+		memcpy(name,"ecb(cipher_null)",strlen("ecb(cipher_null)"));
+	else
+	{
+		memcpy(name,"not-supported",strlen("not-supported"));
+		ALOGD("xfrm_encry_algo_parse not supported algorithm--%s\n",encry_src);
+	}
+}
+
+void xfrm_interg_algo_parse(char * interg_src, char *name)
+{
+	if(interg_src == NULL)
+		memcpy(name,"digest_null",strlen("digest_null"));
+	else 	if(strcmp(interg_src,"hmac-md5")==0)
+		memcpy(name,"hmac(md5)",strlen("hmac(md5)"));
+	else 	if(strcmp(interg_src,"hmac-sha1")==0)
+		memcpy(name,"hmac(sha1)",strlen("hmac(sha1)"));
+	else 	if(strcmp(interg_src,"hmac-sha256")==0)
+		memcpy(name,"hmac(sha256)",strlen("hmac(sha256)"));
+	else 	if(strcmp(interg_src,"hmac-sha384)")==0)
+		memcpy(name,"hmac(sha384)",strlen("hmac(sha384)"));
+	else 	if(strcmp(interg_src,"hmac-sha512")==0)
+		memcpy(name,"hmac(sha512)",strlen("hmac(sha512)"));
+	else 	if(strcmp(interg_src,"hmac-rmd160")==0)
+		memcpy(name,"hmac(rmd160)",strlen("hmac(rmd160)"));
+	else 	if(strcmp(interg_src,"aes-xcbc")==0)
+		memcpy(name,"xcbc(aes)",strlen("xcbc(aes)"));
+	else 	if(strcmp(interg_src,"cmac(aes)")==0)
+		memcpy(name,"aes-cmac",strlen("aes-cmac"));
+	else 	if(strcmp(interg_src,"null")==0)
+		memcpy(name,"digest_null",strlen("digest_null"));
+	else
+	{
+		memcpy(name,"not-supported",strlen("not-supported"));
+		ALOGD("xfrm_interg_algo_parse not supported algorithm--%s\n",interg_src);
+	}
+}
+
+
+int xfrm_algo_parse(struct xfrm_algo *alg, char *name, char *key, char *buf, int max)
+{
+	int len;
+	int slen = strlen(key);
+
+	strncpy(alg->alg_name, name, sizeof(alg->alg_name));
+
+	if (slen > 2 && strncmp(key, "0x", 2) == 0) {
+		/* split two chars "0x" from the top */
+		char *p = key + 2;
+		int plen = slen - 2;
+		int i;
+		int j;
+
+		/* Converting hexadecimal numbered string into real key;
+		 * Convert each two chars into one char(value). If number
+		 * of the length is odd, add zero on the top for rounding.
+		 */
+
+		/* calculate length of the converted values(real key) */
+		len = (plen + 1) / 2;
+		if (len > max)
+		{
+			ALOGD("xfrm_algo_parse key(len:%d) makes buffer overflow\n",len);
+			return -1;
+		}
+
+		for (i = - (plen % 2), j = 0; j < len; i += 2, j++) {
+			char vbuf[3];
+			__u8 val;
+
+			vbuf[0] = i >= 0 ? p[i] : '0';
+			vbuf[1] = p[i + 1];
+			vbuf[2] = '\0';
+
+			if (get_u8(&val, vbuf, 16))
+			{
+				ALOGD("xfrm_algo_parse key(len:%s) is invalid\n",key);
+				return -1;
+			}
+			buf[j] = val;
+		}
+	} else {
+		len = slen;
+		if (len > 0) {
+			if (len > max)
+			{
+				ALOGD("xfrm_algo_parse key(len:%d) makes buffer overflow\n",len);
+				return -1;
+			}
+
+			strncpy(buf, key, len);
+		}
+	}
+
+	alg->alg_key_len = len * 8;
+
+	return 0;
+}
+
+__u8 xfrm_dir_parse(char * dir_str)
+{
+	__u8 dir;
+	if(strcmp(dir_str,"out")==0)
+		dir = XFRM_POLICY_OUT;
+	else if(strcmp(dir_str,"in")==0)
+		dir = XFRM_POLICY_IN;
+	else if(strcmp(dir_str,"fwd")==0)
+		dir = XFRM_POLICY_FWD;
+	else
+		dir = XFRM_POLICY_ERROR;
+	return dir;
+}
+
+int xfrm_mode_parse(__u8 *mode, char * mode_str)
+{
+
+
+	if (strcmp(mode_str, "transport") == 0)
+		*mode = XFRM_MODE_TRANSPORT;
+	else if (strcmp(mode_str, "tunnel") == 0)
+		*mode = XFRM_MODE_TUNNEL;
+	else if (strcmp(mode_str, "ro") == 0)
+		*mode = XFRM_MODE_ROUTEOPTIMIZATION;
+	else if (strcmp(mode_str, "in_trigger") == 0)
+		*mode = XFRM_MODE_IN_TRIGGER;
+	else if (strcmp(mode_str, "beet") == 0)
+		*mode = XFRM_MODE_BEET;
+	else
+		return -1;
+
+
+	return 0;
+}
+
+void xfrm_selector_parse(struct xfrm_selector *sel, char * src,char * dst,enum PROTOCOL_TYPE protocol,char * src_port,char * dst_port)
+{
+
+	inet_prefix dst_prefix;
+	inet_prefix src_prefix;
+
+	memset(&dst_prefix, 0, sizeof(dst_prefix));
+	memset(&src_prefix, 0, sizeof(src_prefix));
+
+
+	get_prefix(&src_prefix, src, AF_UNSPEC);
+	memcpy(&sel->saddr, &src_prefix.data, sizeof(sel->saddr));
+	sel->prefixlen_s = src_prefix.bitlen;
+
+	get_prefix(&dst_prefix, dst, AF_UNSPEC);
+	memcpy(&sel->daddr, &dst_prefix.data, sizeof(sel->daddr));
+	sel->prefixlen_d = dst_prefix.bitlen;
+
+	sel->family = dst_prefix.family;
+
+	sel->sport = htons(atoi(src_port));
+	sel->dport = htons(atoi(dst_port));
+	sel->dport_mask = ~((__u16)0);
+	sel->sport_mask = ~((__u16)0);
+
+	sel->user = getpid();
+
+	sel->proto = protocol;
+#ifdef INIT_ENG_BUILD
+	if(sel->family == AF_INET)
+	ALOGD("xfrm_selector_parse family:%u,prefix_d:%u,prefix_s:%u,daddr:0x%x,saddr:0x%x,sel->sport:%d,sel->dport:%d,proto:%u,user:%u\n",sel->family,sel->prefixlen_d,sel->prefixlen_s,sel->daddr.a4,sel->daddr.a4,sel->sport,sel->dport,sel->proto,sel->user);
+	else
+	ALOGD("xfrm_selector_parse family:%u,prefix_d:%u,prefix_s:%u,daddr:0x%x %x %x %x,saddr:0x%x %x %x %x ,sel->sport:%d,sel->dport:%d,proto:%u,user:%u\n",sel->family,sel->prefixlen_d,sel->prefixlen_s,sel->daddr.a6[0],sel->daddr.a6[1],sel->daddr.a6[2],sel->daddr.a6[3],sel->saddr.a6[0],sel->saddr.a6[1],sel->saddr.a6[2],sel->saddr.a6[3],sel->sport,sel->dport,sel->proto,sel->user);
+#endif
+}
+
+
+
diff --git a/src/connectivity/libipsecims/setkey_xfrm_parse.h b/src/connectivity/libipsecims/setkey_xfrm_parse.h
new file mode 100644
index 0000000..0ce4635
--- /dev/null
+++ b/src/connectivity/libipsecims/setkey_xfrm_parse.h
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <time.h>
+#include <linux/capability.h>
+#include <linux/ipsec.h>
+#include <sys/capability.h>
+#include <cutils/properties.h>
+#include "utils_xfrm.h"
+
+struct typeent {
+	const char *t_name;
+	int t_type;
+};
+
+
+
+extern int xfrm_xfrmproto_getbyname(char *name);
+extern int xfrm_id_parse(xfrm_address_t *saddr_xfrm, struct xfrm_id *id, __u16 *family,
+		 char * src,char * dst,char * ipsec_type);
+extern int xfrm_algo_parse(struct xfrm_algo *alg, char *name, char *key, char *buf, int max);
+extern __u8 xfrm_dir_parse(char * dir_str);
+extern int xfrm_mode_parse(__u8 *mode, char * mode_str);
+extern void xfrm_selector_parse(struct xfrm_selector *sel, char * src,char * dst,enum PROTOCOL_TYPE protocol,char * src_port,char * dst_port);
+extern void xfrm_encry_algo_parse(char * encry_src, char *name);
+extern void xfrm_interg_algo_parse(char * interg_src, char *name);
diff --git a/src/connectivity/libipsecims/utils_xfrm.c b/src/connectivity/libipsecims/utils_xfrm.c
new file mode 100644
index 0000000..178a19b
--- /dev/null
+++ b/src/connectivity/libipsecims/utils_xfrm.c
@@ -0,0 +1,230 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <resolv.h>
+#include <asm/types.h>
+#include <linux/pkt_sched.h>
+#include <time.h>
+#include <sys/time.h>
+#include <errno.h>
+#include "utils_xfrm.h"
+#define LOG_TAG "setkey"
+#include <log/log.h>
+#include <cutils/log.h>
+
+
+int mask2bits(__u32 netmask_xfrm)
+{
+	unsigned bits_xfrm = 0;
+	__u32 mask_xfrm = ntohl(netmask_xfrm);
+	__u32 host_xfrm = ~mask_xfrm;
+
+	/* a valid netmask must be 2^n - 1 */
+	if ((host_xfrm & (host_xfrm + 1)) != 0)
+		return -1;
+
+	for (; mask_xfrm; mask_xfrm <<= 1)
+		++bits_xfrm;
+	return bits_xfrm;
+}
+
+int get_netmask(unsigned *val_xfrm, const char *arg_xfrm, int base_xfrm)
+{
+	inet_prefix addr_xfrm;
+
+	if (!get_unsigned(val_xfrm, arg_xfrm, base_xfrm))
+		return 0;
+
+	/* try coverting dotted quad to CIDR */
+	if (!get_addr_1(&addr_xfrm, arg_xfrm, AF_INET) && addr_xfrm.family == AF_INET) {
+		int b_xfrm = mask2bits(addr_xfrm.data[0]);
+
+		if (b_xfrm >= 0) {
+			*val_xfrm = b_xfrm;
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
+int get_unsigned(unsigned *val_xfrm, const char *arg_xfrm, int base_xfrm)
+{
+	unsigned long res_xfrm = 0;
+	char *ptr_xfrm = NULL;
+
+	if (!arg_xfrm || !*arg_xfrm)
+		return -1;
+	res_xfrm = strtoul(arg_xfrm, &ptr_xfrm, base_xfrm);
+	if (!ptr_xfrm || ptr_xfrm == arg_xfrm || *ptr_xfrm || res_xfrm > UINT_MAX)
+		return -1;
+	*val_xfrm = res_xfrm;
+	return 0;
+}
+
+
+int get_u32(__u32 *val_xfrm, const char *arg_xfrm, int base_xfrm)
+{
+	unsigned long res_xfrm = 0;
+	char *ptr_xfrm = NULL;
+
+	if (!arg_xfrm || !*arg_xfrm)
+		return -1;
+	res_xfrm = strtoul(arg_xfrm, &ptr_xfrm, base_xfrm);
+	if (!ptr_xfrm || ptr_xfrm == arg_xfrm || *ptr_xfrm || res_xfrm > 0xFFFFFFFFUL)
+		return -1;
+	*val_xfrm = res_xfrm;
+	return 0;
+}
+
+
+int get_u8(__u8 *val_xfrm, const char *arg_xfrm, int base_xfrm)
+{
+	unsigned long res_xfrm = 0;
+	char *ptr_xfrm = NULL;
+
+	if (!arg_xfrm || !*arg_xfrm)
+		return -1;
+	res_xfrm = strtoul(arg_xfrm, &ptr_xfrm, base_xfrm);
+	if (!ptr_xfrm || ptr_xfrm == arg_xfrm || *ptr_xfrm || res_xfrm > 0xFF)
+		return -1;
+	*val_xfrm = res_xfrm;
+	return 0;
+}
+
+
+
+/* This uses a non-standard parsing (ie not inet_aton, or inet_pton)
+ * because of legacy choice to parse 10.8 as 10.8.0.0 not 10.0.0.8
+ */
+int get_addr_ipv4(__u8 *ap_xfrm, const char *cp_xfrm)
+{
+	int i_xfrm = 0;
+
+	for (i_xfrm = 0; i_xfrm < 4; i_xfrm++) {
+		unsigned long n_xfrm = 0;
+		char *endp_xfrm = NULL;
+
+		n_xfrm = strtoul(cp_xfrm, &endp_xfrm, 0);
+		if (n_xfrm > 255)
+			return -1;	/* bogus network value */
+
+		if (endp_xfrm == cp_xfrm) /* no digits */
+			return -1;
+
+		ap_xfrm[i_xfrm] = n_xfrm;
+
+		if (*endp_xfrm == '\0')
+			break;
+
+		if (i_xfrm == 3 || *endp_xfrm != '.')
+			return -1; 	/* extra characters */
+		cp_xfrm = endp_xfrm + 1;
+	}
+
+	return 1;
+}
+
+int get_addr_1(inet_prefix *addr_xfrm, const char *name_xfrm, int family)
+{
+	memset(addr_xfrm, 0, sizeof(*addr_xfrm));
+
+	if (strcmp(name_xfrm, "default") == 0 ||
+	    strcmp(name_xfrm, "all") == 0 ||
+	    strcmp(name_xfrm, "any") == 0) {
+		if (family == AF_DECnet)
+			return -1;
+		addr_xfrm->family = family;
+		addr_xfrm->bytelen = (family == AF_INET6 ? 16 : 4);
+		addr_xfrm->bitlen = -1;
+		return 0;
+	}
+
+	if (strchr(name_xfrm, ':')) {
+		addr_xfrm->family = AF_INET6;
+		if (family != AF_UNSPEC && family != AF_INET6)
+			return -1;
+		if (inet_pton(AF_INET6, name_xfrm, addr_xfrm->data) <= 0)
+			return -1;
+		addr_xfrm->bytelen = 16;
+		addr_xfrm->bitlen = -1;
+		return 0;
+	}
+
+
+	addr_xfrm->family = AF_INET;
+	if (family != AF_UNSPEC && family != AF_INET)
+		return -1;
+
+	if (get_addr_ipv4((__u8 *)addr_xfrm->data, name_xfrm) <= 0)
+		return -1;
+
+	addr_xfrm->bytelen = 4;
+	addr_xfrm->bitlen = -1;
+	return 0;
+}
+
+int get_prefix(inet_prefix *dst_xfrm, char *arg_xfrm, int family)
+{
+	int err = 0 ;
+	unsigned plen  = 0;
+	char *slash = NULL;
+
+	memset(dst_xfrm, 0, sizeof(*dst_xfrm));
+
+	if (strcmp(arg_xfrm, "default") == 0 ||
+	    strcmp(arg_xfrm, "any") == 0 ||
+	    strcmp(arg_xfrm, "all") == 0) {
+		if (family == AF_DECnet)
+			return -1;
+		dst_xfrm->family = family;
+		dst_xfrm->bytelen = 0;
+		dst_xfrm->bitlen = 0;
+		return 0;
+	}
+
+	slash = strchr(arg_xfrm, '/');
+	if (slash)
+		*slash = 0;
+
+	err = get_addr_1(dst_xfrm, arg_xfrm, family);
+	if (err == 0) {
+		switch(dst_xfrm->family) {
+			case AF_INET6:
+				dst_xfrm->bitlen = 128;
+				break;
+			case AF_DECnet:
+				dst_xfrm->bitlen = 16;
+				break;
+			default:
+			case AF_INET:
+				dst_xfrm->bitlen = 32;
+		}
+		if (slash) {
+			if (get_netmask(&plen, slash+1, 0)
+					|| plen > dst_xfrm->bitlen) {
+				err = -1;
+				goto done;
+			}
+			dst_xfrm->flags |= PREFIXLEN_SPECIFIED;
+			dst_xfrm->bitlen = plen;
+		}
+	}
+done:
+	if (slash)
+		*slash = '/';
+	return err;
+}
+
+
+
+
+
diff --git a/src/connectivity/libipsecims/utils_xfrm.h b/src/connectivity/libipsecims/utils_xfrm.h
new file mode 100644
index 0000000..60d519a
--- /dev/null
+++ b/src/connectivity/libipsecims/utils_xfrm.h
@@ -0,0 +1,109 @@
+#ifndef __UTILS_XFRM_H__
+#define __UTILS_XFRM_H__ 1
+#include <string.h>
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_link.h>
+#include <linux/if_addr.h>
+#include <linux/neighbour.h>
+#include <cutils/properties.h>
+#include <asm/types.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <linux/xfrm.h>
+
+
+//#define NLMSG_DELETEALL_BUF_SIZE (4096-512)
+#define NLMSG_DELETEALL_BUF_SIZE 8192
+
+/*
+ * Receiving buffer defines:
+ * nlmsg
+ *   data = struct xfrm_userpolicy_info
+ *   rtattr
+ *     data = struct xfrm_user_tmpl[]
+ */
+#define NLMSG_BUF_SIZE 4096
+#define RTA_BUF_SIZE 2048
+#define XFRM_TMPLS_BUF_SIZE 1024
+#define CTX_BUF_SIZE 256
+#define XFRM_ALGO_KEY_BUF_SIZE 512
+
+#undef NLMSG_TAIL
+#define NLMSG_TAIL(nmsg) \
+	((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+
+#define XFRM_POLICY_ERROR 255
+enum PROTOCOL_TYPE{
+	PROTOCOL_ICMP=1,
+	PROTOCOL_IPV4=4,
+	PROTOCOL_TCP=6,
+	PROTOCOL_UDP=17,
+	PROTOCOL_IPV6=41,
+	PROTOCOL_GRE=47,
+	PROTOCOL_ESP=50,
+	PROTOCOL_AH=51,
+	PROTOCOL_ICMPV6=58,
+	PROTOCOL_IPCOMP=108,
+	PROTOCOL_L2TP=115
+};
+
+struct rtnl_handle_xfrm
+{
+	int			fd;
+	struct sockaddr_nl	local;
+	struct sockaddr_nl	peer;
+	__u32			seq;
+	__u32			dump;
+};
+
+struct req_handle_xfrm {
+	struct nlmsghdr			n;
+	struct xfrm_userpolicy_info	xpinfo;
+	char				buf[RTA_BUF_SIZE];
+	} ;
+
+typedef struct
+{
+	__u8 family;
+	__u8 bytelen;
+	__s16 bitlen;
+	__u32 flags;
+	__u32 data[8];
+} inet_prefix;
+
+#define PREFIXLEN_SPECIFIED 1
+
+static inline __u32 nl_mgrp_xfrm(__u32 group)
+{
+	if (group > 31 ) {
+		//ALOGD("Use setsockopt for this group %d\n", group);
+		return -1;
+	}
+	return group ? (1 << (group - 1)) : 0;
+}
+
+
+extern int mask2bits(__u32 netmask_xfrm);
+extern int get_netmask(unsigned *val_xfrm, const char *arg_xfrm, int base_xfrm);
+extern int get_unsigned(unsigned *val_xfrm, const char *arg_xfrm, int base_xfrm);
+extern int get_u32(__u32 *val_xfrm, const char *arg_xfrm, int base_xfrm);
+extern int get_u8(__u8 *val_xfrm, const char *arg_xfrm, int base_xfrm);
+extern int get_addr_ipv4(__u8 *ap_xfrm, const char *cp_xfrm);
+extern int get_addr_1(inet_prefix *addr_xfrm, const char *name_xfrm, int family);
+extern int get_prefix(inet_prefix *dst_xfrm, char *arg_xfrm, int family);
+
+
+
+typedef int (*rtnl_filter_t_xfrm)(struct rtnl_handle_xfrm * rth,struct nlmsghdr *n);
+
+extern int xfrm_policy_process_delete_exist( struct rtnl_handle_xfrm * rth,struct nlmsghdr *n, pid_t volte_pid);
+extern int xfrm_state_process_delete_exist( struct rtnl_handle_xfrm * rth,struct nlmsghdr *n, pid_t volte_pid);
+
+extern void rtnl_close_xfrm(struct rtnl_handle_xfrm *rth);
+extern int rtnl_open_byproto_xfrm(struct rtnl_handle_xfrm *rth, unsigned subscriptions,
+		      int protocol);
+extern int rtnl_listen_xfrm(struct rtnl_handle_xfrm *rtnl, rtnl_filter_t_xfrm handler);
+extern int rtnl_accept_msg_xfrm(struct rtnl_handle_xfrm * rth,struct nlmsghdr *n);
+#endif /* __UTILS_XFRM_H__ */