#include #include #include #include #include #include #include #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 list,save 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(®, IPV4_PATTERN, REG_EXTENDED | REG_NEWLINE); } else { retval = regcomp(®, IPV6_PATTERN, REG_EXTENDED | REG_NEWLINE); } retval = regexec(®,ip_addr, sizeof match / sizeof match[0], match, 0); printf("%s is %s\n", ip_addr, retval == 0 ? "legal" : "illegal"); regfree(®); 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; }