#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <arpa/inet.h> | |
#include <linux/netlink.h> | |
#include <linux/socket.h> | |
#include <sys/socket.h> | |
#include <syslog.h> | |
#include <sys/klog.h> | |
#include <stdarg.h> | |
#include "ipsec_api.h" | |
#include <assert.h> | |
static void LOG_PRINT(int priority, const char* fmt, ...) | |
{ | |
va_list args = {0}; | |
char buff[512]; | |
memset(buff, 0x00, sizeof(buff)); | |
va_start(args, fmt); | |
vsnprintf(buff, sizeof(buff), fmt, args); | |
va_end(args); | |
syslog(priority,"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%s", buff); | |
printf("%s\n", buff); | |
} | |
//ÓÉÓÚiprouteÖв»´æÔÚ½«¡°udp¡±¡¢¡°tcp¡±×Ô¶¯×ª»»ÎªÏàÓ¦´«Êä²ãÐÒéºÅµÄ¹¦ÄÜ£¬Òò´ËÔÚÅäÖÃipsecʱ£¬Ö±½ÓʹÓô«Êä²ãÐÒéºÅÅäÖÃproto²ÎÊý | |
int ipsec_set(int s, void *data, int datalen) | |
{ | |
ipsec_set_msg *set_msg = (ipsec_set_msg *)data; | |
unsigned short client_port, server_port; | |
int spi; | |
char * source_addr, *dest_addr, *auth_key, *crypto_key, *xfrmproto, *mode, *ealg, *alg, *dir; | |
char cmd[512]; | |
if(s < 0) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set:socket s is not legal"); | |
return -1; | |
} | |
if (data == NULL) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set:data is not legal"); | |
return -1; | |
} | |
if(datalen != sizeof(ipsec_set_msg)) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set:The length of msg is not legal"); | |
return -1; | |
} | |
crypto_key = set_msg->Ckey; | |
xfrmproto = set_msg->Prot; | |
mode = set_msg->Mod; | |
ealg = set_msg->Ealg; | |
alg = set_msg->Alg; | |
dir = set_msg->dir; | |
auth_key = set_msg->Ikey; | |
client_port = set_msg->PortC; | |
server_port = set_msg->PortS; | |
spi = set_msg->Spi; | |
if (1 == set_msg->IsIpv4) | |
{ | |
source_addr = set_msg->SrcIpv4; | |
dest_addr = set_msg->DestIpv4; | |
} | |
else | |
{ | |
source_addr = set_msg->SrcIpv6; | |
dest_addr = set_msg->DestIpv6; | |
} | |
if(0 == strcmp(alg,"hmac-md5-96")) | |
{ | |
memset(alg,0x00,strlen(alg)); | |
sprintf(alg,"md5"); | |
} | |
else if (0 == strcmp(alg,"hmac-sha-1-96")) | |
{ | |
memset(alg,0x00,strlen(alg)); | |
sprintf(alg,"sha1"); | |
} | |
else | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set:ONLY support md5 and sha1 algorithm now, alg %s is not valid",alg); | |
return -1; | |
} | |
if(0 == strcmp(ealg,"aes-cbc")) | |
{ | |
memset(ealg,0x00,strlen(ealg)); | |
sprintf(ealg,"aes"); | |
} | |
else if(0 == strcmp(ealg,"des-ede3-cbc")) | |
{ | |
memset(ealg,0x00,strlen(ealg)); | |
sprintf(ealg,"des3_ede"); | |
} | |
else if(0 == strcmp(ealg,"null")) | |
{ | |
memset(ealg,0x00,strlen(ealg)); | |
sprintf(ealg,"cipher_null"); | |
memset(crypto_key,0x00,strlen(crypto_key)); | |
sprintf(crypto_key,"\"\""); | |
} | |
else | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set:ONLY support aes-cbc£¬des-ede3-cbc and null three crypto algorithm, the alg %s is not valid", ealg); | |
return -1; | |
} | |
memset(cmd, 0x00, sizeof(cmd)); | |
if(0 != strcmp(ealg,"cipher_null")) | |
{ | |
sprintf(cmd, "ip xfrm state add src %s dst %s proto %s spi 0x%x auth %s 0x%s enc %s 0x%s mode %s", | |
source_addr, dest_addr, xfrmproto, spi, alg,auth_key, ealg,crypto_key, mode); | |
} | |
else | |
{ | |
sprintf(cmd, "ip xfrm state add src %s dst %s proto %s spi 0x%x auth %s 0x%s enc %s %s mode %s", | |
source_addr, dest_addr, xfrmproto, spi, alg,auth_key, ealg,crypto_key, mode); | |
} | |
soft_system(cmd); | |
LOG_PRINT(LOG_ALERT,"ipsec_set:%s\n", cmd); | |
memset(cmd, 0x00, sizeof(cmd)); | |
//ÅäÖÃudpÐÒéipsec²ÎÊý£¬udp´«Êä²ãÐÒéºÅΪ17 | |
sprintf(cmd, "ip xfrm policy add dir %s src %s dst %s proto 17 sport %d dport %d ptype main tmpl src %s dst %s proto esp spi %d mode transport", | |
dir, source_addr, dest_addr, client_port, server_port, source_addr, dest_addr, spi); | |
soft_system(cmd); | |
LOG_PRINT(LOG_ALERT,"ipsec_set:%s\n", cmd); | |
memset(cmd, 0x00, sizeof(cmd)); | |
//ÅäÖÃtcpÐÒéipsec²ÎÊý£¬tcp´«Êä²ãÐÒéºÅΪ6 | |
sprintf(cmd, "ip xfrm policy add dir %s src %s dst %s proto 6 sport %d dport %d ptype main tmpl src %s dst %s proto esp spi %d mode transport", | |
dir, source_addr, dest_addr, client_port, server_port, source_addr, dest_addr, spi); | |
soft_system(cmd); | |
LOG_PRINT(LOG_ALERT,"ipsec_set:%s\n", cmd); | |
return 0; | |
} | |
int ipsec_del(int s, void *data, int datalen) | |
{ | |
ipsec_del_msg * p_del_msg = (ipsec_del_msg *)data; | |
ipsec_del_msg * del_msg = NULL; | |
unsigned short client_port, server_port; | |
int spi, i; | |
char * source_addr, *dest_addr, *auth_key, *crypto_key, *xfrmproto, *mode, *ealg, *alg, *dir; | |
char cmd[512]; | |
if(s < 0) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_del:socket s is not legal"); | |
return -1; | |
} | |
if (data == NULL) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_del:data is not legal"); | |
return -1; | |
} | |
if( 0!= datalen%sizeof(ipsec_del_msg)) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_del:The length of msg is not legal"); | |
return -1; | |
} | |
for(i = 0;i<datalen/sizeof(ipsec_del_msg);i++) | |
{ | |
del_msg = p_del_msg+i; | |
crypto_key = del_msg->Ckey; | |
xfrmproto = del_msg->Prot; | |
mode = del_msg->Mod; | |
ealg = del_msg->Ealg; | |
alg = del_msg->Alg; | |
dir = del_msg->dir; | |
auth_key = del_msg->Ikey; | |
client_port = del_msg->PortC; | |
server_port = del_msg->PortS; | |
spi = del_msg->Spi; | |
if (1 == del_msg->IsIpv4) | |
{ | |
source_addr = del_msg->SrcIpv4; | |
dest_addr = del_msg->DestIpv4; | |
} | |
else | |
{ | |
source_addr = del_msg->SrcIpv6; | |
dest_addr = del_msg->DestIpv6; | |
} | |
memset(cmd, 0x00, sizeof(cmd)); | |
sprintf(cmd,"ip xfrm state delall spi 0x%x",spi); | |
soft_system(cmd); | |
LOG_PRINT(LOG_ALERT,"ipsec_del:%s\n", cmd); | |
memset(cmd, 0x00, sizeof(cmd)); | |
//ɾ³ýudpÐÒéipsecÅäÖà | |
sprintf(cmd, "ip xfrm policy delall dir %s src %s dst %s proto 17 sport %d dport %d",dir, source_addr, dest_addr, client_port, server_port); | |
soft_system(cmd); | |
LOG_PRINT(LOG_ALERT,"ipsec_del:%s\n", cmd); | |
memset(cmd, 0x00, sizeof(cmd)); | |
//ɾ³ýtcpÐÒéipsecÅäÖà | |
sprintf(cmd, "ip xfrm policy delall dir %s src %s dst %s proto 6 sport %d dport %d ",dir, source_addr, dest_addr, client_port, server_port); | |
soft_system(cmd); | |
LOG_PRINT(LOG_ALERT,"ipsec_del:%s\n", cmd); | |
} | |
return 0; | |
} | |
#if 0 | |
int ipsec_set_sa(int s, void *data, int datalen) | |
{ | |
ipsec_set_sa_msg * set_sa_msg = (ipsec_set_sa_msg *)data; | |
int spi; | |
char * source_addr, *dest_addr, *auth_key, *crypto_key, *xfrmproto, *mode, *ealg, *alg; | |
char cmd[512]; | |
if(s < 0) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sa:socket s is not legal"); | |
return -1; | |
} | |
if (data == NULL) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sa:data is not legal"); | |
return -1; | |
} | |
if(datalen != sizeof(ipsec_set_sa_msg)) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sa:The length of msg is not legal"); | |
return -1; | |
} | |
crypto_key = set_sa_msg->Ckey; | |
xfrmproto = set_sa_msg->XfrmProt; | |
mode = set_sa_msg->Mod; | |
ealg = set_sa_msg->Ealg; | |
alg = set_sa_msg->Alg; | |
auth_key = set_sa_msg->Ikey; | |
spi = set_sa_msg->Spi; | |
if (1 == set_sa_msg->IsIpv4) | |
{ | |
source_addr = set_sa_msg->SrcIpv4; | |
dest_addr = set_sa_msg->DestIpv4; | |
} | |
else | |
{ | |
source_addr = set_sa_msg->SrcIpv6; | |
dest_addr = set_sa_msg->DestIpv6; | |
} | |
if(0 == strcmp(alg,"hmac-md5-96")) | |
{ | |
memset(alg,0x00,sizeof(alg)); | |
sprintf(alg,"md5"); | |
} | |
else if (0 == strcmp(alg,"hmac-sha-1-96")) | |
{ | |
memset(alg,0x00,sizeof(alg)); | |
sprintf(alg,"sha1"); | |
} | |
else | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sa:ONLY support md5 and sha1 algorithm now, alg %s is not valid",alg); | |
return -1; | |
} | |
if(0 == strcmp(ealg,"aes-cbc")) | |
{ | |
memset(ealg,0x00,sizeof(ealg)); | |
sprintf(ealg,"aes"); | |
} | |
else if(0 == strcmp(ealg,"des-ede3-cbc")) | |
{ | |
memset(ealg,0x00,sizeof(ealg)); | |
sprintf(ealg,"des3_ede"); | |
} | |
else if(0 == strcmp(ealg,"null")) | |
{ | |
memset(ealg,0x00,sizeof(ealg)); | |
sprintf(ealg,"cipher_null"); | |
memset(crypto_key,0x00,sizeof(crypto_key)); | |
sprintf(crypto_key,"\"\""); | |
} | |
else | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sa:ONLY support aes-cbc£¬des-ede3-cbc and null three crypto algorithm, the alg %s is not valid", ealg); | |
return -1; | |
} | |
memset(cmd, 0x00, sizeof(cmd)); | |
if(0 != strcmp(ealg,"cipher_null")) | |
{ | |
sprintf(cmd, "ip xfrm state add src %s dst %s proto %s spi 0x%x auth %s 0x%s enc %s 0x%s mode %s", | |
source_addr, dest_addr, xfrmproto, spi, alg,auth_key, ealg,crypto_key, mode); | |
} | |
else | |
{ | |
sprintf(cmd, "ip xfrm state add src %s dst %s proto %s spi 0x%x auth %s 0x%s enc %s %s mode %s", | |
source_addr, dest_addr, xfrmproto, spi, alg,auth_key, ealg, crypto_key, mode); | |
} | |
system(cmd); | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sa:%s\n", cmd); | |
return 0; | |
} | |
int ipsec_set_sp(int s, void *data, int datalen) | |
{ | |
ipsec_set_sp_msg * set_sp_msg = (ipsec_set_sp_msg *)data; | |
unsigned short client_port, server_port; | |
int proto; | |
char * source_addr, *dest_addr, *dir; | |
char cmd[512], cmd_tcp[512]; | |
int offset = 0, offset_tcp = 0; | |
if(s < 0) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sp:socket s is not legal"); | |
return -1; | |
} | |
if (data == NULL) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sp:data is not legal"); | |
return -1; | |
} | |
if(datalen != sizeof(ipsec_set_sp_msg)) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sp:The length of msg is not legal"); | |
return -1; | |
} | |
proto = set_sp_msg->Prot; | |
dir = set_sp_msg->dir; | |
client_port = set_sp_msg->PortC; | |
server_port = set_sp_msg->PortS; | |
if (1 == set_sp_msg->IsIpv4) | |
{ | |
source_addr = set_sp_msg->SrcIpv4; | |
dest_addr = set_sp_msg->DestIpv4; | |
} | |
else | |
{ | |
source_addr = set_sp_msg->SrcIpv6; | |
dest_addr = set_sp_msg->DestIpv6; | |
} | |
if( proto < IPSEC_PROTO_BASE || proto > IPSEC_PROTO_MAX) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sp:ipsec protocol only support tcp and udp now!\n"); | |
return -1; | |
} | |
memset(cmd, 0x00, sizeof(cmd)); | |
offset += sprintf(cmd + offset, "ip xfrm policy add "); | |
if( 0 != strlen(dir)) | |
{ | |
offset += sprintf(cmd + offset,"dir %s ", dir); | |
} | |
if( 0 != strlen(source_addr)) | |
{ | |
offset += sprintf(cmd + offset, "src %s ", source_addr); | |
} | |
if( 0 != strlen(dest_addr)) | |
{ | |
offset += sprintf(cmd + offset, "dst %s ", dest_addr); | |
} | |
if( (IPSEC_PROTO_UNKOWN == proto) && (client_port || server_port)) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sp:ipsec_del_sp : msg must have protocol messages when port is not equal to zero!\n"); | |
return -1; | |
} | |
else if( IPSEC_PROTO_UNKOWN == proto) | |
{ | |
system(cmd); | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sp:%s\n", cmd); | |
} | |
else | |
{ | |
offset_tcp += sprintf(cmd_tcp + offset_tcp, "%s",cmd); | |
if( proto&IPSEC_PROTO_UDP) | |
{ | |
offset += sprintf(cmd + offset, "proto 17 "); | |
if(client_port) | |
{ | |
offset += sprintf(cmd + offset,"sport %d ", client_port); | |
} | |
if(server_port) | |
{ | |
offset += sprintf(cmd + offset,"dport %d ", server_port); | |
} | |
system(cmd); | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sp:%s\n", cmd); | |
} | |
if(proto&IPSEC_PROTO_TCP) | |
{ | |
offset_tcp += sprintf(cmd_tcp + offset_tcp, "proto 6 "); | |
if(client_port) | |
{ | |
offset_tcp += sprintf(cmd_tcp + offset_tcp,"sport %d ", client_port); | |
} | |
if(server_port) | |
{ | |
offset_tcp += sprintf(cmd_tcp + offset_tcp,"dport %d ", server_port); | |
} | |
system(cmd_tcp); | |
LOG_PRINT(LOG_ALERT,"ipsec_set_sp:%s\n", cmd_tcp); | |
} | |
} | |
return 0; | |
} | |
int ipsec_del_sa(int s, void *data, int datalen) | |
{ | |
ipsec_del_sa_msg * del_sa_msg = (ipsec_del_sa_msg *)data; | |
int spi; | |
char * source_addr, *dest_addr, *xfrmproto, *mode; | |
int offset = 0; | |
char cmd[512]; | |
if(s < 0) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sa:socket s is not legal"); | |
return -1; | |
} | |
if (data == NULL) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sa:data is not legal"); | |
return -1; | |
} | |
if(datalen != sizeof(ipsec_del_sa_msg)) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sa:The length of msg is not legal"); | |
return -1; | |
} | |
xfrmproto = del_sa_msg->XfrmProt; | |
mode = del_sa_msg->Mod; | |
spi = del_sa_msg->Spi; | |
if (1 == del_sa_msg->IsIpv4) | |
{ | |
source_addr = del_sa_msg->SrcIpv4; | |
dest_addr = del_sa_msg->DestIpv4; | |
} | |
else | |
{ | |
source_addr = del_sa_msg->SrcIpv6; | |
dest_addr = del_sa_msg->DestIpv6; | |
} | |
memset(cmd, 0x00, sizeof(cmd)); | |
offset += sprintf(cmd + offset, "ip xfrm state delall "); | |
if( 0 != strlen(source_addr)) | |
{ | |
offset += sprintf(cmd + offset, "src %s ",source_addr); | |
} | |
if( 0 != strlen(dest_addr)) | |
{ | |
offset += sprintf(cmd + offset, "dst %s ",dest_addr); | |
} | |
if( 0 != strlen(xfrmproto)) | |
{ | |
offset += sprintf(cmd + offset, "proto %s ", xfrmproto); | |
} | |
if( 0 != spi) | |
{ | |
offset += sprintf(cmd + offset, "spi 0x%x ",spi); | |
} | |
if( 0 != strlen(mode)) | |
{ | |
offset += sprintf(cmd + offset, "mode %s ", mode); | |
} | |
system(cmd); | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sa:%s\n", cmd); | |
return 0; | |
} | |
int ipsec_del_sp(int s, void *data, int datalen) | |
{ | |
ipsec_del_sp_msg * del_sp_msg = (ipsec_del_sp_msg *)data; | |
unsigned short client_port, server_port; | |
int proto; | |
char * source_addr, *dest_addr, *dir; | |
char cmd[512], cmd_tcp[512]; | |
int offset = 0, offset_tcp = 0; | |
if(s < 0) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sp:socket s is not legal"); | |
return -1; | |
} | |
if (data == NULL) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sp:data is not legal"); | |
return -1; | |
} | |
if(datalen != sizeof(ipsec_del_sp_msg)) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sp:The length of msg is not legal"); | |
return -1; | |
} | |
proto = del_sp_msg->Prot; | |
dir = del_sp_msg->dir; | |
client_port = del_sp_msg->PortC; | |
server_port = del_sp_msg->PortS; | |
if (1 == del_sp_msg->IsIpv4) | |
{ | |
source_addr = del_sp_msg->SrcIpv4; | |
dest_addr = del_sp_msg->DestIpv4; | |
} | |
else | |
{ | |
source_addr = del_sp_msg->SrcIpv6; | |
dest_addr = del_sp_msg->DestIpv6; | |
} | |
if( proto < IPSEC_PROTO_BASE || proto > IPSEC_PROTO_MAX) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sp:ipsec protocol only support tcp and udp now!\n"); | |
return -1; | |
} | |
memset(cmd, 0x00, sizeof(cmd)); | |
offset += sprintf(cmd + offset, "ip xfrm policy delall "); | |
if( 0 != strlen(dir)) | |
{ | |
offset += sprintf(cmd + offset,"dir %s ", dir); | |
} | |
if( 0 != strlen(source_addr)) | |
{ | |
offset += sprintf(cmd + offset, "src %s ", source_addr); | |
} | |
if( 0 != strlen(dest_addr)) | |
{ | |
offset += sprintf(cmd + offset, "dst %s ", dest_addr); | |
} | |
if( (IPSEC_PROTO_UNKOWN == proto) && (client_port || server_port)) | |
{ | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sp:ipsec_del_sp : msg must have protocol messages when port is not equal to zero!\n"); | |
return -1; | |
} | |
else if( IPSEC_PROTO_UNKOWN == proto) | |
{ | |
system(cmd); | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sp:%s\n", cmd); | |
} | |
else | |
{ | |
offset_tcp += sprintf(cmd_tcp + offset_tcp, "%s",cmd); | |
if( proto&IPSEC_PROTO_UDP) | |
{ | |
offset += sprintf(cmd + offset, "proto 17 "); | |
if(client_port) | |
{ | |
offset += sprintf(cmd + offset,"sport %d ", client_port); | |
} | |
if(server_port) | |
{ | |
offset += sprintf(cmd + offset,"dport %d ", server_port); | |
} | |
system(cmd); | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sp:%s\n", cmd); | |
} | |
if(proto&IPSEC_PROTO_TCP) | |
{ | |
offset_tcp += sprintf(cmd_tcp + offset_tcp, "proto 6 "); | |
if(client_port) | |
{ | |
offset_tcp += sprintf(cmd_tcp + offset_tcp,"sport %d ", client_port); | |
} | |
if(server_port) | |
{ | |
offset_tcp += sprintf(cmd_tcp + offset_tcp,"dport %d ", server_port); | |
} | |
system(cmd_tcp); | |
LOG_PRINT(LOG_ALERT,"ipsec_del_sp:%s\n", cmd_tcp); | |
} | |
} | |
return 0; | |
} | |
#endif |