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