[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
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;
+}
+