#include <pthread.h>
#include <unistd.h>
#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"
#include "rpdb.h"
#if 0
rm -fr /tmp/nf_conntrack*
cp -fr /proc/net/nf_conntrack /tmp/nf_conntrack
cat /tmp/nf_conntrack |awk -F ' ' '{print $4}'|xargs -I {} echo {} >> /tmp/nf_conntrack_proto;
cat /tmp/nf_conntrack |awk -F ' ' '{print $7}' |  awk -F '=' '{print $2}' |xargs -I {} echo {} >> /tmp/nf_conntrack_dip;
cat /tmp/nf_conntrack |awk -F ' ' '{print $9}' |  awk -F '=' '{print $2}' |xargs -I {} echo {} >> /tmp/nf_conntrack_dport;
paste /tmp/nf_conntrack_proto /tmp/nf_conntrack_dip /tmp/nf_conntrack_dport | xargs -I {} echo {} >>/tmp/dpi_triple1;
sort -k2n /tmp/dpi_triple1 | uniq > /tmp/dpi_triple
#endif

struct rpdb_mark {
	struct list_head list;
	union {
		struct in6_addr  ip6;
		struct in_addr   ip4;
	}ip;
	bool ipv4;
	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}(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4}){0,4}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))(%.+)?\s*$" 

#define  RPDP_MARK_HASH_DEPTH (1024)
static int gRpdbMark = 0;

/*
 * mark hash list,save mark
 */
static struct list_head gRpdbMarkList[RPDP_MARK_HASH_DEPTH] = {0};
static int gRpdbTableIndex = 1; /* 1 - 252 */

static pthread_mutex_t mutex;

#define IPV4_ADDR (1)
#define IPV6_ADDR (2)
struct rpdb_stat{
	char table_name[256];
	int index;
};
struct rpdb_stat rpdbstat[256] = {0};
/*
	popen
*/

void print_result(FILE *fp)
{
	char buf[100];

	if(!fp) 
	{
		return;
	}
     
	memset(buf, 0, sizeof(buf));
	fgets(buf, sizeof(buf) - 1, fp);
	printf("%s", buf);
	return;
}
 
int rpdb_popen(char *cmd)
{
    FILE *fp = popen(cmd, "r");
	if(!fp) 
	{
		perror("popen");
		exit(EXIT_FAILURE);
	}
	print_result(fp);
	pclose(fp);
   return 0;
}

int rpdb_system(char *cmd)
{
	return system(cmd);
}

/*
 *  rpdb 初始化接口
*/
bool rpdb_init_route()
{
	FILE *fp = NULL;
	int i = 0;
	char cmd[256] = {0};
	/*
		初始化多路由表
	*/
	rpdb_popen("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);

	/*
		初始化策略路由规则,ip rule
	*/
	memset(cmd,0,sizeof(cmd));
	sprintf(cmd,"%s","ip rule|grep fwmark|awk -F ' ' '{print $7}'|xargs -I {} ip rule del table {}");
	rpdb_system(cmd);
	
	
	/*
		flush 路由
	*/
	memset(cmd,0,sizeof(cmd));
	sprintf(cmd,"%s","ip route flush cache");
	rpdb_system(cmd);
	
	/*
		初始化链表
	*/
	for (i = 0; i < RPDP_MARK_HASH_DEPTH; i++)
	{
		INIT_LIST_HEAD(&gRpdbMarkList[i]);
	}
	
	
	memset((char*)&rpdbstat,0,256*sizeof(struct rpdb_stat));
	
	pthread_mutex_init(&mutex, NULL);

	return true;
}


int rpdb_calc(char *name,int flag)
{
	int i = 0;
	int j = 0;
	int flag1 = 0;
	/*
		路由表存在,只修改路由表对应的策略数
	*/
	for (i = 0; i < 256; i++)
	{
		if (strcmp(name,rpdbstat[i].table_name) == 0)
		{
			if (flag == RPDB_ROUTE_ADD)
			{
				rpdbstat[i].index++;
			}
			else if(flag == RPDB_ROUTE_DEL)
			{
				rpdbstat[i].index--;
			}
			if(rpdbstat[i].index == 0)
				memset(rpdbstat[i].table_name,0,sizeof(rpdbstat[i].table_name));
			flag1 = 1;
			break;
		}
	}
	
	/*
		路由表不存在,添加路由表name,并赋值策略数
	*/
	if (flag1 == 0)
	{
		for (j = 0; j < 256; j++)
		{
			
			if (flag == RPDB_ROUTE_ADD)
			{
				if(!rpdbstat[j].table_name[0])
				{
					strcpy(rpdbstat[j].table_name,name);
					rpdbstat[j].index = 1;
					//printf("%s,%d,index:%d,%s\n",__FUNCTION__,__LINE__,rpdbstat[j].index,rpdbstat[j].table_name);
					return rpdbstat[j].index;
				}
				
			}
		}
	}
	
}

int rpdb_get_index(char* name)
{
	int i = 0;
	for (i = 0; i < 256; i++)
	{
		if (strcmp(name,rpdbstat[i].table_name) == 0)
		{
			return rpdbstat[i].index;
		}
	}
	return 0;
}

#if 0
inet_pton(AF_INET6, "2a01:198:603:0:396e:4789:8e99:890f", &ip);
printf("0x%x%x%x%x\n", htonl(ip.s6_addr32[0]),htonl(ip.s6_addr32[1]),htonl(ip.s6_addr32[2]),htonl(ip.s6_addr32[3]));

inet_pton(AF_INET6, "2a01:198:603:0::", &ip);
printf("0x%x%x%x%x\n", htonl(ip.s6_addr32[0]),htonl(ip.s6_addr32[1]),htonl(ip.s6_addr32[2]),htonl(ip.s6_addr32[3]));
#endif
int is_valid_ipv4(char *ipv4)
{
    struct in_addr addr;
    if(ipv4 == NULL)
        return 0;
    if(inet_pton(AF_INET, ipv4, (void *)&addr) == 1)
	{
        return 1;
	}
    return 0;
}

int is_valid_ipv6(char *ipv6)
{
    struct in6_addr addr6;
    if(ipv6 == NULL)
        return 0;
    if(inet_pton(AF_INET6, ipv6, (void *)&addr6) == 1)
	{
        return 1;
	}
    return 0;
}


/*
 * 判断ip地址是否合法
 */
#if 0
int rpdb_ipaddr_match(char *ip_addr,int flag)
{
    regex_t reg;
    regmatch_t match[1];
    int retval = 0;

	if (flag == IPV4_ADDR)
	{
   		retval = regcomp(&reg, IPV4_PATTERN, REG_EXTENDED | REG_NEWLINE);
	}
	else if(flag == IPV6_ADDR)
	{
		retval = regcomp(&reg, IPV6_PATTERN, REG_EXTENDED | REG_NEWLINE);	
	}
	else
	{
		return -1;
	}
	
    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);
	if (retval == 0) 
		return 1;
	else
		return 0;
}
#endif

/*
	1 - 成功
	0 - 失败
*/

int rpdb_ipaddr_match(char *ip_addr,int flag)
{
	if (flag == IPV4_ADDR)
	{
		return is_valid_ipv4(ip_addr);
	}
	else if (flag == IPV6_ADDR)
	{
		return is_valid_ipv6(ip_addr);
	}
	return 0;
}


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)
{
	int i = 0;
	if (node1.ipv4 == true)
	{
		if (node1.ip.ip4.s_addr == node2.ip.ip4.s_addr)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	else
	{
		for (i = 0; i < 4; i++){
			if (node1.ip.ip6.s6_addr32[i] != node2.ip.ip6.s6_addr32[i]){
				return  false;
			}
		}
	}

	return true;
}


/*
 *  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(char* gateway)
{
	in_addr_t  addr;
	if (NULL == gateway)
	{
		return -1;
	}

	addr = inet_addr(gateway);
	struct rpdb_mark node;
	node.ipv4 = false;
	if(rpdb_ipaddr_match(gateway,IPV4_ADDR) == 1)
	{
		node.ip.ip4.s_addr = addr;
		node.ipv4 = true;
	}
	else if(rpdb_ipaddr_match(gateway,IPV6_ADDR) == 1)
	{
		inet_pton(AF_INET6, gateway, (void *)&node.ip.ip6);
		node.ipv4 = false;
	}
	else
	{
		return -1;
	}
	
	return rpdb_mark_hash_add(node);
}

int rpdb_add_route(char *gateway,char *table_name)
{
	char cmd[256] = {0};
	char cmd1[256] = {0};
	int ret = 0;
	int mark = 0;
	
	if(rpdb_ipaddr_match(gateway,IPV6_ADDR) == 1)
	{
		sprintf(cmd,"ip -6 route add default via %s table %s",gateway,table_name);
		sprintf(cmd1,"ip -6 route del default via %s table %s",gateway,table_name);
	} 
	else 
	{
		sprintf(cmd,"ip route add default via %s table %s",gateway,table_name);
		sprintf(cmd1,"ip route del default via %s table %s",gateway,table_name);
	}
	
	/*先删除之前可能存在的路由,否则添加路由可能会报错*/
	rpdb_system(cmd1);
	
	/*添加路由*/
	ret = rpdb_system(cmd);
	printf("%s,%d,ret=%d,%s\n",__FUNCTION__,__LINE__,ret,cmd);
	if(ret != 0)
	{
		return -1;
	}	
	mark = rpdb_gen_mark(gateway);
	memset(cmd,0,sizeof(cmd));
	sprintf(cmd,"ip rule add fwmark %d table %s",mark,table_name);
	ret = rpdb_system(cmd);
	if (ret != 0)
		return -1;
	/*
		刷新路由
	*/
	memset(cmd,0,sizeof(cmd));
	sprintf(cmd,"%s","ip route flush cache");
	ret = rpdb_system(cmd);
	if (ret != 0)
		return -1;
		
	printf("%s,%d,ret=%d,%s\n",__FUNCTION__,__LINE__,ret,cmd);
	return 0;
}


int rpdb_del_route(char *gateway,char *table_name)
{
	char cmd[256] = {0};
	int ret = 0;
	if (strstr(":",gateway))
	{
		sprintf(cmd,"ip -6 route del default via %s table %s",gateway,table_name);
	} 
	else 
	{
		sprintf(cmd,"ip route del default via %s table %s",gateway,table_name);
	}
	

	ret = rpdb_system(cmd);
	if (ret != 0)
		return -1;
		
	memset(cmd,0,sizeof(cmd));
	sprintf(cmd,"ip rule del table %s",table_name);
	ret = rpdb_system(cmd);
	if (ret != 0)
		return -1;
		
	/*
		刷新路由
	*/
	memset(cmd,0,sizeof(cmd));
	sprintf(cmd,"%s","ip route flush cache");
	ret = rpdb_system(cmd);
	if (ret != 0)
		return -1;
		
	printf("%s,%d,ret=%d,%s\n",__FUNCTION__,__LINE__,ret,cmd);
	return 0;
}

/*
	返回nexthop对应的策略数
*/
int rpdb_add_delete_table(char *gateway,char* tbl_name,int op)
{
	char line_cnt[1024] = {0};
	FILE *fp = NULL;
	FILE *fp_tmp = NULL;
	bool ret = false;
	int i = 0;
	int cn_num = 0;
	int index = 0;
	int mark = 0;
	char table_name[256] = {0};
	int flag = 0;
	
	/*
		判断ip地址是否合法
	*/
	if((rpdb_ipaddr_match(gateway,IPV6_ADDR) == 0)&&
		(rpdb_ipaddr_match(gateway,IPV4_ADDR) == 0))
	{
		printf("ipv addr invalid:%s\n",gateway);
		return -1;
	}

	
	/*
		生成路由表名字
	*/
	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 -1;
		}
	}
	printf("tbl_name:%s\n",table_name);
	mark = rpdb_gen_mark(gateway);	
	
	
	index = rpdb_get_index(table_name);
	printf("%s,%d,index=%d\n",__FUNCTION__,__LINE__,index);
	fp = fopen(RT_TABLES_PATH,"ra+");
	if (NULL == fp)
	{
		return -1;
	}


	/*
		向文件最后一行添加   路由表项
	*/
	if (op == RPDB_ROUTE_ADD)
	{
		while(!feof(fp))  /*  遍历文件每一行,查找 路由表是否存在              */
		{
			memset(line_cnt,0,1024);
			fgets(line_cnt,1024,fp);
			if(strstr(line_cnt,table_name))
			{
				rpdb_calc(table_name,RPDB_ROUTE_ADD);
				fclose(fp);
				return  mark;
			}			
		}
		
		if (gRpdbTableIndex > 252)
		{
			return -1;
		}
		
		memset(line_cnt,0,1024);
		sprintf(line_cnt,"%d	%s",gRpdbTableIndex,table_name);

		fprintf(fp,"%s\n",line_cnt);
		fclose(fp);
		gRpdbTableIndex++;
		
		if(0 == rpdb_add_route(gateway,table_name))
		{
			rpdb_calc(table_name,RPDB_ROUTE_ADD);
			return  mark;
		}
		else
		{
			/*
				删除路由表
			*/
			fp = fopen(RT_TABLES_PATH,"ra+");
			if(NULL == fp) return -1;
			fp_tmp = fopen("/tmp/rt_tables","w");
			if (fp_tmp == NULL)
			{
				fclose(fp);
			      	return -1;
			}
			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 -1;
		}
	}

	if (op == RPDB_ROUTE_DEL)
	{
		if(index < 1)
		{
			fclose(fp);
			return -1;
		}
		
		if(index > 1)
		{
			fclose(fp);
			rpdb_calc(table_name,RPDB_ROUTE_DEL);
			return mark;
		}
			
		if (NULL == fp)
		{
			return -1;
		}
		else
		{
			fp_tmp = fopen("/tmp/rt_tables","w");
			if (fp_tmp == NULL) 
			{
				fclose(fp);
				return -1;
			}
			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);
				}
				else
				{
					flag = 1;
					/*
					 删除路由表之前先把路由删掉
					*/
					if(0 == rpdb_del_route(gateway,table_name))
					{
						rpdb_calc(table_name,RPDB_ROUTE_DEL);
					}	
				}
			}

			fclose(fp);
			fclose(fp_tmp);
			system("cp -fr /tmp/rt_tables /etc/iproute2/rt_tables");
			if (flag == 1)
			{
				return mark;
			}
			else
			{
				return  -1;
			}
		}
	}
	fclose(fp);
	return -1;
}
/*
 *  路由添加接口
*/

int  rpdb_add_del_route(char* gateway,char *tbl_name,int opt)
{
	return rpdb_add_delete_table(gateway,tbl_name,opt);
}

#if 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);
	rpdb_ipaddr_match("fe80:0000:0000:0000:0204:61ff:fe9d:f5",2);
	struct rpdb_mark mark_value;
	struct rpdb_mark mark_value1;
	in_addr_t  addr;
	rpdb_init_route();
	addr = inet_addr("table_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);


	/*
		192.168.221.2 为有效的下一跳网关地址,添加成功
	*/
	printf("~~~~~~%d\n",rpdb_add_del_route("192.168.221.2",NULL,RPDB_ROUTE_ADD));
	printf("~~~~~~%d\n",rpdb_add_del_route("192.168.221.2","test_table",RPDB_ROUTE_ADD));
	printf("~~~~~~%d\n",rpdb_add_del_route("192.168.221.2",NULL,RPDB_ROUTE_DEL));
	printf("~~~~~~%d\n",rpdb_add_del_route("192.168.221.2","test_table",RPDB_ROUTE_DEL));
	printf("~~~~~~%d\n",rpdb_add_del_route("192.168.221.2",NULL,RPDB_ROUTE_ADD));
	printf("~~~~~~%d\n",rpdb_add_del_route("192.168.221.2","test_table",RPDB_ROUTE_ADD));
	printf("~~~~~~%d\n",rpdb_add_del_route("192.168.221.2",NULL,RPDB_ROUTE_DEL));
	printf("~~~~~~%d\n",rpdb_add_del_route("192.168.221.2","test_table",RPDB_ROUTE_DEL));
	printf("~~~~~~%d\n",rpdb_add_del_route("192.168.221.2",NULL,RPDB_ROUTE_ADD));
	printf("~~~~~~%d\n",rpdb_add_del_route("192.168.221.2","test_table",RPDB_ROUTE_ADD));
	printf("~~~~~~%d\n",rpdb_add_del_route("192.168.221.2",NULL,RPDB_ROUTE_DEL));
	printf("~~~~~~%d\n",rpdb_add_del_route("192.168.221.2","test_table",RPDB_ROUTE_DEL));
	
	/*
		错误的网关地址
	*/
	printf("~~~~~~%d\n",rpdb_add_del_route("172.168.221.2",NULL,RPDB_ROUTE_ADD));
	printf("~~~~~~%d\n",rpdb_add_del_route("112.168.221.2",NULL,RPDB_ROUTE_ADD));
	
	
	/*
		非法IP地址
	*/
	printf("~~~~~~%d\n",rpdb_add_del_route("392.168.221.2",NULL,RPDB_ROUTE_ADD));
	
		printf("~~~~~~%d\n",rpdb_add_del_route("2a01:198:603:0:396e:4789:8e99:890f",NULL,RPDB_ROUTE_ADD));
	return 0;
}
#endif