blob: c2cffba9e97c0f087e7a08cde700e5e9c0374f0f [file] [log] [blame]
#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;
}