|  | #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; | 
|  | } | 
|  |  |