blob: 377ac46412669a6a34c40960571975c78b2371af [file] [log] [blame]
#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