#include "flowood.h" #include "flowood_fun.h" #include "flwd_net.h" #include "MESA_htable.h" #include "MESA_list_queue.h" #include "MESA_handle_logger.h" #include "MESA_list_count.h" #include "Maat_rule.h" #include #include #include #include #include #include #include #include #include #include static unsigned int flwd_fetch_policy_id_from_user_region(struct Maat_rule_t *maat_res) { char *policy_section; /* 策略组号, 存储于自定义域, 即当前策略的IP地址池的组号 */ policy_section = strcasestr(maat_res->service_defined, "IR_STRATEGY="); if(NULL == policy_section){ return 0; } policy_section += strlen("IR_STRATEGY="); return (unsigned int)atoi(policy_section); } /* 根据当前客户端的源IP, PORT, 扫描命中哪个复用策略: policy_id. return value: > 0: success, policy id. 0: not hit rule; */ unsigned int flwd_access_maat_scan_rule(int tid, const flwd_tuple5_t *tuple5) { int ret; struct Maat_rule_t maat_res[1]; /* 不太可能多命中, 即便是多命中, 最后也只能要一个结果, 此处res设为1 */ struct ipaddr client_addr; scan_status_t mid = NULL; unsigned int hit_policy_id; memset(&maat_res[0], 0, sizeof(maat_res)); flwd_tuple5_to_stream_addr(tid, tuple5, &client_addr); ret = Maat_scan_addr(flwd_global_val.maat_static_handle, flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_POLICY_IP].table_id, /* TODO, SNAT和DNAT策略分开, table_id分成两个!! */ &client_addr, maat_res, 1, &mid, tid); if(ret <= 0){ return 0; } hit_policy_id = flwd_fetch_policy_id_from_user_region(&maat_res[0]); return hit_policy_id; } static void nouse_maat_start_cb(int update_type,void* u_para) { return; } static void nouse_maat_finish_cb(void* u_para) { return; } struct layer_addr_mac_in_mac { unsigned char outer_dst_mac[6]; /* 最外层mac地址, network order */ unsigned char outer_src_mac[6]; /* 最外层mac地址, network order */ unsigned char inner_dst_mac[6]; /* 内层mac地址, network order */ unsigned char inner_src_mac[6]; /* 内层mac地址, network order */ }; /* ascii字符转16进制 */ static char MESA_ascii_to_hex(char ascii) { char c = 0; switch(ascii) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': c = ascii - 0x30; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': c = 10 + ascii - 0x61; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': c = 10 + ascii - 0x41; break; } return c; } /* "000100032202-00e0fc030007,000100032202-00e0fc030007" copy from sapp. */ static int flwd_mac_in_mac_pton(char *addr_str, struct layer_addr_mac_in_mac *minm) { int i; char *str_val = addr_str; unsigned char tmp_bin_val; memset(minm, 0, sizeof(struct layer_addr_mac_in_mac)); for(i = 0; i < 6; i++){ tmp_bin_val = 0; /* 先清零, 后续赋值语句都是或操作 */ if(isxdigit(*str_val)==0){ printf("MAC string type error!\n"); return -1; } tmp_bin_val |= MESA_ascii_to_hex(*str_val) << 4; str_val++; if(isxdigit(*str_val)==0) { printf("MAC string type error!\n"); return -1; } tmp_bin_val |= MESA_ascii_to_hex(*str_val); str_val++; minm->inner_src_mac[i] = tmp_bin_val; } if(*str_val != '-'){ printf("MAC string type error!\n"); return -1; } str_val++; for(i = 0; i < 6; i++){ tmp_bin_val = 0; /* 先清零, 后续赋值语句都是或操作 */ if(isxdigit(*str_val)==0){ printf("MAC string type error!\n"); return -1; } tmp_bin_val |= MESA_ascii_to_hex(*str_val) << 4; str_val++; if(isxdigit(*str_val)==0) { printf("MAC string type error!\n"); return -1; } tmp_bin_val |= MESA_ascii_to_hex(*str_val); str_val++; minm->inner_dst_mac[i] = tmp_bin_val; } if(*str_val != ','){ printf("MAC_IN_MAC string type error!\n"); return -1; } str_val++; for(i = 0; i < 6; i++){ tmp_bin_val = 0; /* 先清零, 后续赋值语句都是或操作 */ if(isxdigit(*str_val)==0){ printf("MAC string type error!\n"); return -1; } tmp_bin_val |= MESA_ascii_to_hex(*str_val) << 4; str_val++; if(isxdigit(*str_val)==0) { printf("MAC string type error!\n"); return -1; } tmp_bin_val |= MESA_ascii_to_hex(*str_val); str_val++; minm->outer_src_mac[i] = tmp_bin_val; } if(*str_val != '-'){ printf("MAC_IN_MAC string type error!\n"); return -1; } str_val++; for(i = 0; i < 6; i++){ tmp_bin_val = 0; /* 先清零, 后续赋值语句都是或操作 */ if(isxdigit(*str_val)==0){ printf("MAC string type error!\n"); return -1; } tmp_bin_val |= MESA_ascii_to_hex(*str_val) << 4; str_val++; if(isxdigit(*str_val)==0) { printf("MAC string type error!\n"); return -1; } tmp_bin_val |= MESA_ascii_to_hex(*str_val); str_val++; minm->outer_dst_mac[i] = tmp_bin_val; } return 0; } /* region_id=1;dev_id=1;link_id=2;route_dir=0;smac=xxxxxx;dmac=xxxxx; 其中user_region格式使用MAC-IN-MAC格式,先是内层,后面是外层. inner_smac-inner-dmac, outer_smac-outer_dmat, 000100032202-00e0fc030007,000100032202-00e0fc030007 */ static int flwd_act_ip_user_region_parse(char *user_region, flwd_active_ip_t *act_ip) { int ret; struct layer_addr_mac_in_mac minm; /* TODO flwd_search_fwd_ip_by_gdev_ip(), 通过dev_id, region_id自动查询. */ #if FLWD_RUN_IN_CEIEC_TEST /* 临时测试,手动写死内层mac */ //char manual_inner_smac[6] = {0x3c, 0x97, 0x0e, 0x18, 0x18, 0x41}; //char manual_inner_smac[6] = {0xe4, 0x95, 0x6e, 0x20, 0x0d, 0x06}; char manual_inner_smac[6] = {0x28, 0xd2, 0x44, 0x43, 0x12, 0x34}; /* 活跃IP的SMAC */ char manual_inner_dmac[6] = {0xe8, 0x61, 0x1f, 0x13, 0x70, 0x7a}; /* 目标服务器MAC */ //inet_pton(AF_INET, "10.3.127.3", &act_ip->gdev_args.gdev_ip_net_order); inet_pton(AF_INET, "10.1.1.1", &act_ip->gdev_args.gdev_ip_net_order); act_ip->gdev_args.link_id = 1; /* TODO, 根据活跃IP参数获取, 华严捕包为1 */ act_ip->gdev_args.this_ip_as_sip_route_dir = 1; /* TODO, 根据活跃IP参数获取,华严捕包为1 */ memcpy(act_ip->gdev_args.inner_raw_smac, manual_inner_smac, 6); memcpy(act_ip->gdev_args.inner_raw_dmac, manual_inner_dmac, 6); #else ret = flwd_mac_in_mac_pton(user_region, &minm); if(ret < 0){ return -1; } memcpy(act_ip->gdev_args.inner_raw_dmac, minm.inner_dst_mac, 6); memcpy(act_ip->gdev_args.inner_raw_smac, minm.inner_src_mac, 6); #endif return 0; } /* 库表格式: ID,addr_type, protocol,ip,port,direction,user_region,location,is_valid,action,service,policy_group,op_time; TODO: 其中user_region格式因前端是否是mac-in-mac格式, 还是原始MAC格式未定, 暂使用gdev_ip=1.1.1.1把GDEVIP传回来. */ static void flwd_ip_static_pool_cb(int table_id, const char *table_line, void* u_para) { char *stack_buf = strdup(table_line); char *save_ptr; char *section; const char *delim = "\t "; flwd_active_ip_t act_ip; int tmp_int; char for_log_ip_str[128]; memset(&act_ip, 0, sizeof(act_ip)); /* ID */ section = strtok_r(stack_buf, delim, &save_ptr); assert(section); /* addr_type */ section = strtok_r(NULL, delim, &save_ptr); assert(section); tmp_int = atoi(section); if(4 == tmp_int){ act_ip.active_ip_net_order.addr_type = FLWD_IP_ADDR_TYPE_V4; act_ip.active_ip_net_order.addr_len = sizeof(int); }else if(6 == tmp_int){ act_ip.active_ip_net_order.addr_type = FLWD_IP_ADDR_TYPE_V6; act_ip.active_ip_net_order.addr_len = sizeof(struct in6_addr); }else{ assert(0); } /* protocol, 暂不关心 */ section = strtok_r(NULL, delim, &save_ptr); assert(section); /* ip */ section = strtok_r(NULL, delim, &save_ptr); assert(section); if(FLWD_IP_ADDR_TYPE_V4 == act_ip.active_ip_net_order.addr_type){ inet_pton(AF_INET, section, &act_ip.active_ip_net_order.addr_ipv4); }else{ inet_pton(AF_INET6, section, &act_ip.active_ip_net_order.addr_ipv6); } strncpy(for_log_ip_str, section, 128); /* port */ section = strtok_r(NULL, delim, &save_ptr); assert(section); tmp_int = atoi(section); if(tmp_int < 0 || tmp_int > 65535){ assert(0); } act_ip.active_ip_net_order.dport = (unsigned short)tmp_int; /* direction, 给GDEV下的方向应该都是目标IP, 0表示源IP,1表示目的IP,2表示双向 */ section = strtok_r(NULL, delim, &save_ptr); assert(section); /* user region, 存储GDEV相关信息 */ section = strtok_r(NULL, delim, &save_ptr); assert(section); if(flwd_act_ip_user_region_parse(section, &act_ip) < 0){ goto done; } /* location, */ section = strtok_r(NULL, delim, &save_ptr); assert(section); #if FLWD_IP_REGION_BY_LIB if(FLWD_IP_ADDR_TYPE_V4 == act_ip.active_ip_net_order.addr_type){ act_ip.ip_region_type = flwd_ipv4_location(ntohl(act_ip.active_ip_net_order.addr_ipv4)); }else{ act_ip.ip_region_type = flwd_ipv6_location(&act_ip.active_ip_net_order.addr_ipv6); } #else tmp_int = atoi(section); if((tmp_int != FLWD_IP_REGION_INLAND) && (tmp_int != FLWD_IP_REGION_OUTLAND)){ assert(0); } act_ip.ip_region_type = (flwd_ip_region_type_t)tmp_int; #endif /* is_valid */ section = strtok_r(NULL, delim, &save_ptr); assert(section); act_ip.is_valid = atoi(section); /* action, TODO, 20180910, 此字段已经删除!!! */ //section = strtok_r(NULL, delim, &save_ptr); //assert(section); /* service */ section = strtok_r(NULL, delim, &save_ptr); assert(section); /* policy group id */ section = strtok_r(NULL, delim, &save_ptr); assert(section); act_ip.policy_group_id = strtoul(section, NULL, 10); /* op_time */ section = strtok_r(NULL, delim, &save_ptr); //assert(section); act_ip.ip_origin_type = FLWD_ACT_IP_STATIC; flwd_act_ip_update(&act_ip); flwd_log(10, "ip_static_pool update callback: recv ip %s, region:%d, policy_id:%u\n", for_log_ip_str, act_ip.ip_region_type, act_ip.policy_group_id); done: while(strtok_r(NULL, delim, &save_ptr)); free(stack_buf); return; } /* 库表格式: ID,addr_type, protocol,ip,port,direction,user_region,location,is_valid,op_time; TODO: 其中user_region格式使用MAC-IN-MAC格式,先是内层,后面是外层. inner_smac-inner-dmac, outer_smac-outer_dmat, 000100032202-00e0fc030007,000100032202-00e0fc030007 */ void flwd_ip_dyn_sift_pool_cb(int table_id,const char* table_line,void* u_para) { char *stack_buf = strdup(table_line); char *save_ptr; char *section; const char *delim = "\t "; flwd_active_ip_t act_ip; int tmp_int; char *for_log_ip_str; memset(&act_ip, 0, sizeof(act_ip)); /* ID */ section = strtok_r(stack_buf, delim, &save_ptr); assert(section); /* addr_type */ section = strtok_r(NULL, delim, &save_ptr); assert(section); tmp_int = atoi(section); if(4 == tmp_int){ act_ip.active_ip_net_order.addr_type = FLWD_IP_ADDR_TYPE_V4; act_ip.active_ip_net_order.addr_len = sizeof(int); }else if(6 == tmp_int){ act_ip.active_ip_net_order.addr_type = FLWD_IP_ADDR_TYPE_V6; act_ip.active_ip_net_order.addr_len = sizeof(struct in6_addr); }else{ assert(0); } /* protocol, 暂不关心 */ section = strtok_r(NULL, delim, &save_ptr); assert(section); /* ip */ section = strtok_r(NULL, delim, &save_ptr); assert(section); if(FLWD_IP_ADDR_TYPE_V4 == act_ip.active_ip_net_order.addr_type){ inet_pton(AF_INET, section, &act_ip.active_ip_net_order.addr_ipv4); }else{ inet_pton(AF_INET6, section, &act_ip.active_ip_net_order.addr_ipv6); } for_log_ip_str = section; /* port, 地址池的PORT字段无意义 */ section = strtok_r(NULL, delim, &save_ptr); assert(section); tmp_int = atoi(section); if(tmp_int < 0 || tmp_int > 65535){ assert(0); } act_ip.active_ip_net_order.dport = (unsigned short)tmp_int; /* direction, 给GDEV下的方向应该都是目标IP, 0表示源IP,1表示目的IP,2表示双向 */ section = strtok_r(NULL, delim, &save_ptr); assert(section); /* user region, 暂不关心 */ section = strtok_r(NULL, delim, &save_ptr); assert(section); if(flwd_act_ip_user_region_parse(section, &act_ip) < 0){ goto done; } /* location, */ section = strtok_r(NULL, delim, &save_ptr); assert(section); #if FLWD_IP_REGION_BY_LIB if(FLWD_IP_ADDR_TYPE_V4 == act_ip.active_ip_net_order.addr_type){ act_ip.ip_region_type = flwd_ipv4_location(ntohl(act_ip.active_ip_net_order.addr_ipv4)); }else{ act_ip.ip_region_type = flwd_ipv6_location(&act_ip.active_ip_net_order.addr_ipv6); } #else tmp_int = atoi(section); if((tmp_int != FLWD_IP_REGION_INLAND) && (tmp_int != FLWD_IP_REGION_OUTLAND)){ assert(0); } act_ip.ip_region_type = (flwd_ip_region_type_t)tmp_int; #endif /* is_valid */ section = strtok_r(NULL, delim, &save_ptr); assert(section); act_ip.is_valid = atoi(section); /* op_time */ section = strtok_r(NULL, delim, &save_ptr); assert(section); act_ip.ip_origin_type = FLWD_ACT_IP_DYNAMIC; flwd_act_ip_update(&act_ip); flwd_log(10, "ip_dynamic_pool update callback: recv ip %s, region:%d\n", for_log_ip_str, act_ip.ip_region_type); done: while(strtok_r(NULL, delim, &save_ptr)); /* 清空strtok缓存 */ free(stack_buf); return; } int flwd_access_maat_init(void) { #if 0 == FLWD_NO_MAAT int ret; ret = flwd_maat_talbe_name_init(); if(ret < 0){ return -1; } flwd_global_val.maat_static_handle = flwd_maat_summon(FLWD_CONFIG_FILE, "maat_static"); if(NULL == flwd_global_val.maat_static_handle){ return -1; } flwd_global_val.maat_dynamic_handle = flwd_maat_summon(FLWD_CONFIG_FILE, "maat_dynamic"); if(NULL == flwd_global_val.maat_dynamic_handle){ return -1; } flwd_maat_table_register(flwd_global_val.maat_static_handle, (int)FLWD_MAAT_TB_IR_POLICY_COMPILE); flwd_maat_table_register(flwd_global_val.maat_static_handle, (int)FLWD_MAAT_TB_IR_POLICY_GROUP); flwd_maat_table_register(flwd_global_val.maat_static_handle, (int)FLWD_MAAT_TB_IR_POLICY_IP); flwd_maat_table_register(flwd_global_val.maat_static_handle, (int)FLWD_MAAT_TB_IR_STATIC_IP_POOL_CB); flwd_maat_table_register(flwd_global_val.maat_dynamic_handle, (int)FLWD_MAAT_TB_IR_DYN_SIFT_IP_CB); flwd_maat_table_register(flwd_global_val.maat_dynamic_handle, (int)FLWD_MAAT_TB_IR_DYN_CONN_IP); ret = Maat_table_callback_register(flwd_global_val.maat_static_handle, flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_STATIC_IP_POOL_CB].table_id, nouse_maat_start_cb, flwd_ip_static_pool_cb, nouse_maat_finish_cb, flwd_global_val.maat_log_handle); if(ret < 0){ flwd_log(30, "Maat_table_callback_register %s error!\n", flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_STATIC_IP_POOL_CB].table_name); return -1; } ret = Maat_table_callback_register(flwd_global_val.maat_dynamic_handle, flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_DYN_SIFT_IP_CB].table_id, nouse_maat_start_cb, flwd_ip_dyn_sift_pool_cb, nouse_maat_finish_cb, flwd_global_val.maat_log_handle); if(ret < 0){ flwd_log(30, "Maat_table_callback_register %s error!\n", flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_DYN_SIFT_IP_CB].table_name); return -1; } #endif return 0; }