secgateway/Platform/user/rpdb/rpdb.c

469 lines
9.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <regex.h>
#include "list.h"
struct rpdb_mark {
struct list_head list;
union {
struct in6_addr ip6;
struct in_addr ip4;
}ip;
int mark;
};
char rt_table[11][128]= {
"# reserved values",
"#",
"255 local",
"254 main",
"253 default",
"0 unspe",
"#",
"# local",
"#",
"#1 inr.ruhep"
};
#define RT_TABLES_PATH ("/etc/iproute2/rt_tables")
#define IPV4_PATTERN "^([0-9]|[1-9][0-9]|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]).([0-9]|[1-9][0-9]|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]).([0-9]|[1-9][0-9]|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]).([0-9]|[1-9][0-9]|1[0-9]{1,2}|2[0-4][0-9]|25[0-5])$"
#define IPV6_PATTERN "^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$"
#define RPDP_MARK_HASH_DEPTH (1024)
static int gRpdbMark = 0;
/*
* mark hash listsave mark
*/
struct list_head gRpdbMarkList[RPDP_MARK_HASH_DEPTH] = {0};
/*
popen
*/
void
print_result(FILE *fp)
{
char buf[100];
if(!fp) {
return;
}
printf("\n>>>\n");
memset(buf, 0, sizeof(buf));
fgets(buf, sizeof(buf) - 1, fp) ;
printf("%s", buf);
printf("\n<<<\n");
}
int rpdb_popen(char *cmd)
{
FILE *fp = NULL;
fp = NULL;
fp = popen(cmd, "r");
if(!fp)
{
perror("popen");
exit(EXIT_FAILURE);
}
print_result(fp);
pclose(fp);
sleep(1);
return 0;
}
/*
* rpdb 初始化接口
*/
bool rpdb_init_route()
{
FILE *fp = NULL;
int i = 0;
system("echo > /etc/iproute2/rt_tables");
fp = fopen(RT_TABLES_PATH,"w");
if (fp)
{
for (i = 0; i < 11; i++)
{
fprintf(fp,"%s\n",rt_table[i]);
}
}
else
{
return false;
}
fclose(fp);
/*
初始化链表
*/
for (i = 0; i < RPDP_MARK_HASH_DEPTH; i++)
{
INIT_LIST_HEAD(&gRpdbMarkList[i]);
}
return true;
}
static int gRpdbTableIndex = 1; /* 1 - 252 */
#define RPDB_TABLE_ADD (0)
#define RPDB_TABLE_DEL (1)
bool rpdb_add_delete_table(const char* gateway,const char *tbl_name,int op)
{
char table_name[128] = {0};
char line_cnt[1024] = {0};
FILE *fp = NULL;
FILE *fp_tmp = NULL;
bool ret = false;
int i = 0;
int cn_num = 0;
if (tbl_name == NULL)
{
memset(table_name,0,sizeof(table_name));
sprintf(table_name,"table_%s",gateway);
}
else
{
if (strlen(tbl_name) < 1) /* 检查name的合法性*/
{
memset(table_name,0,sizeof(table_name));
sprintf(table_name,"%s",tbl_name);
}
else
{
return false;
}
}
fp = fopen(RT_TABLES_PATH,"ra+");
if (NULL == fp)
{
return false;
}
else
{
while(!feof(fp)) /* 遍历文件每一行,查找 路由表是否存在 */
{
memset(line_cnt,0,1024);
fgets(line_cnt,1024,fp);
if(strstr(line_cnt,table_name))
{
if (op == RPDB_TABLE_ADD)
{
fclose(fp);
return true;
}
}
}
}
/*
向文件最后一行添加 路由表项
*/
if (op == RPDB_TABLE_ADD)
{
if (gRpdbTableIndex > 252)
{
return false;
}
memset(line_cnt,0,1024);
sprintf(line_cnt,"%d %s",gRpdbTableIndex,table_name);
printf("RPDB_TABLE_ADD:%s\n",line_cnt);
fprintf(fp,"%s\n",line_cnt);
fclose(fp);
gRpdbTableIndex++;
return true;
}
if (op == RPDB_TABLE_DEL)
{
fp = fopen(RT_TABLES_PATH,"r+");
if (NULL == fp)
{
return false;
}
else
{
fp_tmp = fopen("/tmp/rt_tables","w");
if (fp_tmp == NULL) return false;
while(!feof(fp)) /* 遍历文件每一行,查找 路由表是否存在 */
{
memset(line_cnt,0,1024);
fgets(line_cnt,1024,fp);
if(!strstr(line_cnt,table_name))
{
fprintf(fp_tmp,"%s",line_cnt);
}
}
fclose(fp);
fclose(fp_tmp);
system("cp -fr /tmp/rt_tables /etc/iproute2/rt_tables");
}
}
return true;
}
/*
* 判断ip地址是否合法
*/
int rpdb_ipaddr_match(char *ip_addr,int flag)
{
regex_t reg;
regmatch_t match[1];
int retval = 0;
if (flag == 1)
{
retval = regcomp(&reg, IPV4_PATTERN, REG_EXTENDED | REG_NEWLINE);
}
else
{
retval = regcomp(&reg, IPV6_PATTERN, REG_EXTENDED | REG_NEWLINE);
}
retval = regexec(&reg,ip_addr, sizeof match / sizeof match[0], match, 0);
printf("%s is %s\n", ip_addr, retval == 0 ? "legal" : "illegal");
regfree(&reg);
return retval;
}
int rpdb_ip_hash(struct rpdb_mark node)
{
int ip_value = 0;
int hash = 0;
int i = 0;
if (node.ip.ip4.s_addr !=0 )
{
ip_value = node.ip.ip4.s_addr;
}
else
{
for (i = 0; i < 4; ++i)
{
ip_value += node.ip.ip6.s6_addr32[i];
}
}
hash = (ip_value&0xF) + ((ip_value >> 8)&0xF) + ((ip_value >> 16)&0xF) + ((ip_value >> 24)&0xF);
hash = hash&(1024-1);
return hash;
}
/*
* node比较
*/
bool rpdb_mark_node_compare(struct rpdb_mark node1,struct rpdb_mark node2)
{
if (node1.ip.ip4.s_addr == node2.ip.ip4.s_addr)
{
return true;
}
else
{
return false;
}
}
/*
* mark 查找,返回链上的node节点
*/
struct rpdb_mark * rpdb_mark_search(struct rpdb_mark node)
{
struct list_head * pList;
struct rpdb_mark *pNode;
int hash = rpdb_ip_hash(node);
list_for_each(pList,&gRpdbMarkList[hash]) {
pNode = list_entry(pList,struct rpdb_mark,list);
printf("%s,%d,%d,%d\n",__FUNCTION__,__LINE__,pNode->ip.ip4.s_addr,pNode->mark);
if (rpdb_mark_node_compare(node,*pNode)){
printf("%s,%d,mark = %d\n",__FUNCTION__,__LINE__,pNode->mark);
return pNode;
}
}
return NULL;
}
/*
* mark
*/
int rpdb_mark_hash_add(struct rpdb_mark node)
{
struct rpdb_mark *pNode = NULL;
int hash = 0;
pNode = rpdb_mark_search(node);
if (pNode != NULL)
{
return pNode->mark;
}
pNode = (struct rpdb_mark*)malloc(sizeof(struct rpdb_mark));
if (NULL == pNode)
{
return false;
}
hash = rpdb_ip_hash(node);
node.mark = ++gRpdbMark;
memcpy((char*)pNode,(char*)&node,sizeof(struct rpdb_mark));
printf("%s,%d,%d,%d\n",__FUNCTION__,__LINE__,pNode->ip.ip4.s_addr,pNode->mark);
/*
节点添加到链尾部
*/
list_add_tail(&pNode->list,&gRpdbMarkList[hash]);
return gRpdbMark;
}
/*
* 根据下一跳地址生成mark
*/
int rpdb_gen_mark(const char* gateway)
{
in_addr_t addr;
if (NULL == gateway)
{
return -1;
}
addr = inet_addr(gateway);
struct rpdb_mark node;
node.ip.ip4.s_addr = addr;
return rpdb_mark_hash_add(node);
}
/*
* 路由添加接口
*/
bool rpdb_add_route(const char* gateway,const char *tbl_name)
{
char cmd[256] = {0};
int status = 0;
char table_name[128] = {0};
int mark = 0;
if (tbl_name == NULL)
{
memset(table_name,0,sizeof(table_name));
sprintf(table_name,"table_%s",gateway);
}
else
{
if (strlen(tbl_name) < 1) /* 检查name的合法性*/
{
memset(table_name,0,sizeof(table_name));
sprintf(table_name,"%s",tbl_name);
}
else
{
return false;
}
}
if (rpdb_add_delete_table(gateway,tbl_name,RPDB_TABLE_ADD) == false)
{
return false;
}
if (strstr(":",gateway))
{
sprintf(cmd,"ip -6 route add default via %s table %s",gateway,table_name);
}
else
{
sprintf(cmd,"ip route add default via %s table %s",gateway,table_name);
}
printf("%s\n",cmd);
rpdb_popen(cmd);
mark = rpdb_gen_mark(gateway);
memset(cmd,0,sizeof(cmd));
sprintf(cmd,"ip rule add fwmark %d table %s",mark,table_name);
printf("%s\n",cmd);
rpdb_popen(cmd);
return 0;
}
int main()
{
//ipaddr_match("192.168.1.1",1);
//ipaddr_match("192.168.1.300",1);
//ipaddr_match("2000:0:0:0:0:0:0:1 ",2);
//ipaddr_match("fe80:0000:0000:0000:0204:61ff:fe9d:ffffff15",2);
struct rpdb_mark mark_value;
struct rpdb_mark mark_value1;
in_addr_t addr;
rpdb_init_route();
rpdb_add_delete_table("1.1.2.1",NULL,RPDB_TABLE_ADD);
rpdb_add_delete_table("1.1.2.1",NULL,RPDB_TABLE_ADD);
rpdb_add_delete_table("1.2.2.1",NULL,RPDB_TABLE_ADD);
rpdb_add_delete_table("2.1.2.1",NULL,RPDB_TABLE_ADD);
rpdb_add_delete_table("2.1.2.1",NULL,RPDB_TABLE_DEL);
//rpdb_add_delete_table("2.1.2.1",NULL,RPDB_TABLE_DEL);
//rpdb_add_delete_table("1.1.2.1",NULL,RPDB_TABLE_DEL);
addr = inet_addr("2006.6.6.6");
mark_value.ip.ip4.s_addr = addr;
rpdb_mark_hash_add(mark_value);
rpdb_mark_hash_add(mark_value);
rpdb_mark_hash_add(mark_value);
rpdb_mark_hash_add(mark_value);
addr = inet_addr("7.7.7.7");
mark_value1.ip.ip4.s_addr = addr;
rpdb_mark_hash_add(mark_value1);
rpdb_mark_hash_add(mark_value1);
rpdb_add_route("1.2.3.3",NULL);
rpdb_add_route("2.2.4.3",NULL);
rpdb_add_route("3.2.4.3",NULL);
rpdb_add_route("4.2.4.3",NULL);
return 0;
}