summaryrefslogtreecommitdiff
path: root/src/access
diff options
context:
space:
mode:
authorlijia <[email protected]>2018-10-24 09:36:45 +0800
committerlijia <[email protected]>2018-10-24 09:36:45 +0800
commit86a43b4d325ddc850fa9dc4711670880f35b11e8 (patch)
tree8356a056ac9bfb8cf14fcf57f113dd306b4277d1 /src/access
create new project.
Diffstat (limited to 'src/access')
-rw-r--r--src/access/Makefile26
-rw-r--r--src/access/flowood_access.c1656
-rw-r--r--src/access/flwd_access_active_ip_manage.c616
-rw-r--r--src/access/flwd_access_idle_call.c66
-rw-r--r--src/access/flwd_access_ip_layer.c6
-rw-r--r--src/access/flwd_access_l2tp_layer.c22
-rw-r--r--src/access/flwd_access_maat.c582
7 files changed, 2974 insertions, 0 deletions
diff --git a/src/access/Makefile b/src/access/Makefile
new file mode 100644
index 0000000..be17825
--- /dev/null
+++ b/src/access/Makefile
@@ -0,0 +1,26 @@
+#CC=gcc
+CC=g++
+CCC=g++
+
+TARGET=flowood_access.o flwd_access_ip_layer.o flwd_access_active_ip_manage.o flwd_access_idle_call.o flwd_access_maat.o
+
+CFLAGS=-g -fPIC -shared -D_GNU_SOURCE=1 -D_BSD_SOURCE=1 -D__USE_MISC=1 -D__FAVOR_BSD=1 -D__USE_BSD=1
+
+H_DIR=-I../..//inc
+H_DIR+=-I/opt/MESA/include
+H_DIR+=-I/opt/MESA/include/MESA
+
+LIBPATH=../lib
+LIB=-L/opt/MESA/lib -lpthread
+
+
+all:$(TARGET)
+
+.c.o:
+ $(CC) -c $(CFLAGS) -I. $(H_DIR) $<
+
+.cpp.o:
+ $(CCC) -c $(CFLAGS) -I. $(H_DIR) $<
+
+clean:
+ rm -f *.o
diff --git a/src/access/flowood_access.c b/src/access/flowood_access.c
new file mode 100644
index 0000000..6af4866
--- /dev/null
+++ b/src/access/flowood_access.c
@@ -0,0 +1,1656 @@
+#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 "ltsm.h"
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+#include <assert.h>
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+
+/*
+ IP����ϵͳ��������, ��������ն˵�����, ���ݲ���ѡ���ض�IP��, ��NATת��,
+ ���͸�ת������,
+ �Զ������̷�ʽ����.
+*/
+
+static int flwd_access_fetch_usable_ipport_by_single_ip(
+ flwd_active_ip_t *flwd_active_ip, flwd_active_ip_port_args_t *usable_active_ipport_args)
+{
+ int ret;
+ int try_times;
+ MESA_list_count_t *usable_sport_queue_head, *sport_list_node;
+ unsigned short sport;
+ long buf_len;
+ flwd_tuple5_t seek_nat_key;
+ unsigned int compat_io_hash;
+ char ip_str[64];
+ int usable_sport_num;
+
+ if(IPPROTO_TCP == usable_active_ipport_args->protocol){
+ usable_sport_queue_head = &flwd_active_ip->usable_tcp_sport_list_head;
+ }else{
+ usable_sport_queue_head = &flwd_active_ip->usable_udp_sport_list_head;
+ }
+
+ usable_sport_num = MESA_list_count_get_count(usable_sport_queue_head);
+ if(usable_sport_num <= 0){
+ /* ��ǰIP���ö˿���ȫ�������� */
+ flwd_log(20, "ip_pool: %s, all usable sport is in used!\n",
+ flwd_ipt_ntop_r(&flwd_active_ip->active_ip_net_order, ip_str, 64));
+ return ITERATE_CB_RET_CONTINUE_FLAG;
+ }
+
+ flwd_tuple5_dup_to_stack(usable_active_ipport_args->tid, &seek_nat_key, usable_active_ipport_args->nat_key);
+
+ flwd_tuple5_adjust_dir(&seek_nat_key);
+
+ if(FLWD_IP_ADDR_TYPE_V4 == flwd_active_ip->active_ip_net_order.addr_type){
+ seek_nat_key.ippair_v4.sip_net_order = flwd_active_ip->active_ip_net_order.addr_ipv4;
+ }else{
+ memcpy(&seek_nat_key.ippair_v6->sip_net_order,
+ &flwd_active_ip->active_ip_net_order.addr_ipv6,
+ sizeof(struct in6_addr));
+ }
+
+ /*
+ TODO,
+ �˴�ѡ����ԴIP, ��Ҫѡ����ʵ�Դ�˿�, ʹ�ظ��������ܷ�������ǰ���͵��߳�,
+ ����ʹ��ring_queue, ��Ҫ��ͣ�ı������Կ��ö˿�, ֱ��hashֵ���Ϸ�������.
+ */
+ sport_list_node = usable_sport_queue_head->nextele;
+
+ for(try_times = 0;
+ (try_times < usable_sport_num) && (sport_list_node != usable_sport_queue_head);
+ try_times++, sport_list_node = sport_list_node->nextele){
+ /* �������ж˿�, �鿴�ĸ����ɵ���Ԫ��HASH���ɷ��ϵ�ǰ�߳�id */
+ memcpy(&seek_nat_key.sport_net_order, &sport_list_node->quiddity, sizeof(short));
+ compat_io_hash = compat_marsio_tuple4_hash(&seek_nat_key);
+ if((compat_io_hash % flwd_cfg_val.tot_thread_count) == usable_active_ipport_args->tid){
+ MESA_list_count_del(usable_sport_queue_head, sport_list_node); /* �ӿ��ö˿��������Ƴ� */
+ free(sport_list_node); /* �˿��Ѿ���ȡ��, ������������ṹ */
+ goto bingo;
+ }
+ }
+
+ /* ��Ȼ�п��ö˿�, ���ǵ�ǰIPû�ҵ��ʺϵ�ǰ�߳�, �Թ�����ʵ�HASHֵ����Ѷ˿�, ����������һ��IP */
+ flwd_log(20, "ip_pool: %s,has %d usable sport, but unfortunately no match hash value sport for current thread!\n",
+ usable_sport_num,
+ flwd_ipt_ntop_r(&flwd_active_ip->active_ip_net_order, ip_str, 64), usable_sport_num);
+ return ITERATE_CB_RET_CONTINUE_FLAG ;
+
+bingo:
+ usable_active_ipport_args->act_sip_net_order = flwd_active_ip->active_ip_net_order;
+ usable_active_ipport_args->act_sport_net_order = seek_nat_key.sport_net_order;
+
+ memcpy(&usable_active_ipport_args->gdev_args, &flwd_active_ip->gdev_args, sizeof(flwd_gdev_associated_args_t));
+
+ return ITERATE_CB_RET_BREAK_FLAG | ITERATE_CB_RET_REVERSE_FLAG;
+}
+
+/*
+ NOTE:
+ Ϊ��ͬʱ��Ӧstatic_pool��dynamic_pool, ����һ������,
+ ��ͬ����static_poolΪһ��flwd_active_ip_t�ṹ������, ��Ҫ�ڴ˺�����ѭ������.
+*/
+static int flwd_access_fetch_usable_ipport_by_ip_list_cb(
+ const uchar * key, uint size, void * data, void *user)
+{
+ int ret;
+ flwd_active_ip_t *flwd_active_ip_list_head = (flwd_active_ip_t *)data;
+ flwd_active_ip_t *tmp_node;
+ flwd_active_ip_port_args_t *usable_active_ipport_args = (flwd_active_ip_port_args_t *)user;
+
+ tmp_node = flwd_active_ip_list_head;
+ do{
+ ret = flwd_access_fetch_usable_ipport_by_single_ip(tmp_node, usable_active_ipport_args);
+ if(ITERATE_CB_RET_BREAK_FLAG == ret){
+ break;
+ }
+
+ tmp_node = (flwd_active_ip_t *)tmp_node->active_ip_list_node.nextele->quiddity;
+ }while(flwd_active_ip_list_head != tmp_node);
+
+ return ret|ITERATE_CB_RET_REVERSE_FLAG /* �޸�item˳��, ÿ�����Ӹ�����ַ���ﲻͬ��IP */;
+}
+
+/*
+ ����: ��ʵ�ͻ��˵���Ԫ��;
+ ���: ���õ�Դ��ԾIP;
+
+ ����ֵ:
+ 1 : ���в�������, �����ҵ����ŵ�ǰ���ԵĿ���Դip;
+ 0 : �޲���;
+ -1 : �����˲���, ��û�п���IP;
+
+ service_defined��ʽ:
+ "IR_STRATEGY:123"
+*/
+static int flwd_access_snat_search_policy(int tid,
+ flwd_tuple5_t *tuple5, flwd_active_ip_port_args_t *usable_active_ipport_net_order)
+{
+ unsigned int usable_active_ip = 0;
+ int ret;
+ int found_usable_policy_ip = -1;
+
+#if FLWD_NO_ACTIVE_IP_DISCOVER
+ return 0; /* ��ʱ����, �޲��� */
+#else
+ unsigned int policy_id;
+ MESA_list_t *list_node;
+ flwd_active_ip_t *ip_static_pool_list_head, *list_node_item;
+ flwd_ip_region_type_t ip_pool_retion;
+ unsigned char static_ip_group_key[64];
+ int static_ip_group_key_len = 64;
+
+ policy_id = flwd_access_maat_scan_rule(tid, tuple5);
+ if(0 == policy_id){
+ return 0;
+ }
+
+ flwd_log(10, "tuple4 %s hit policy id:%u\n", flwd_tuple5_ntop(tid, tuple5), policy_id);
+
+ /* ���õ�IPΪ��ǰĿ��IP�ķ��� */
+ if(FLWD_IP_REGION_INLAND == usable_active_ipport_net_order->dip_region_type){
+ ip_pool_retion = FLWD_IP_REGION_OUTLAND;
+ }else{
+ ip_pool_retion = FLWD_IP_REGION_INLAND;
+ }
+
+ flwd_policy_group_id_key_gen(policy_id, static_ip_group_key, &static_ip_group_key_len);
+
+ ip_static_pool_list_head = flwd_ip_pool_search(FLWD_ACT_IP_STATIC,
+ flwd_thread_val[tid].flwd_ip_pool_static_htable[tuple5->addr_type][ip_pool_retion],
+ static_ip_group_key,
+ static_ip_group_key_len);
+ if(NULL == ip_static_pool_list_head){
+ flwd_log(30, "tuple4 %s hit policy id:%u, but no valid ip in static ip_pool!\n",
+ flwd_tuple5_ntop(tid, tuple5), policy_id);
+ return 0;
+ }
+
+ list_node = &ip_static_pool_list_head->active_ip_list_node;
+ do{
+ list_node_item = (flwd_active_ip_t *)list_node->quiddity;
+ /* ����htable_cb����, �˴���key, size�ɲ��� */
+ ret = flwd_access_fetch_usable_ipport_by_single_ip(list_node_item, usable_active_ipport_net_order);
+ if(ITERATE_CB_RET_BREAK_FLAG == ret){
+ found_usable_policy_ip = 1;
+ break;
+ }
+ list_node = list_node->nextele;
+ }while(list_node != &ip_static_pool_list_head->active_ip_list_node);
+
+#endif
+
+ return found_usable_policy_ip;
+}
+
+
+/*
+ �ӵ�ַ����, ���ѡ��һ�����û�ԾIP.
+
+ TODO:
+ �����ͬ�ͻ���, ʹ���˲�ͬ����, ��ͬһ��ԴIP���ڲ�ͬ�ľ�̬��ַ����,
+ ������1.2.3.4��Ϊ����IP, �˿ڷ�Χ�ǰ�access_gateway�������ֵ�,
+ ����ͬһ��access_gateway, ������һ���Ķ˿�, ��ͻ��ô��?
+ ��ô�����ͻ����??!!
+
+ �����ý��汣֤, һ��IP��ַֻ������һ����̬��ַ��.
+*/
+static int flwd_access_snat_fetch_usable_ip_from_pool(
+ MESA_htable_handle table, pthread_rwlock_t *flwd_ip_pool_rwlock, int tid,
+ flwd_tuple5_t *nat_key, flwd_active_ip_port_args_t *usable_active_ipport_args)
+{
+
+ pthread_rwlock_wrlock(flwd_ip_pool_rwlock);
+
+ /* ����htable�İ�ʱ�����ȱ�������, ��ѡ���µ�IP, ����dip�ĵ���, ѡ���෴��Դ��Ծip */
+ MESA_htable_iterate_bytime(table,
+ ITERATE_TYPE_NEWEST_FIRST,
+ flwd_access_fetch_usable_ipport_by_ip_list_cb,
+ usable_active_ipport_args);
+
+ if((0 == usable_active_ipport_args->act_sip_net_order.addr_ipv4)
+ || (0 == memcmp(&usable_active_ipport_args->act_sip_net_order.addr_ipv6,
+ &flwd_global_val.zero_ipv6_addr, sizeof(struct in6_addr)))){
+ pthread_rwlock_unlock(flwd_ip_pool_rwlock);
+ return -1;
+ }
+
+ pthread_rwlock_unlock(flwd_ip_pool_rwlock);
+ return 0;
+}
+
+#if FLWD_SUPPORT_DNAT
+static void * flwd_search_access_dnat_lb_policy(int tid,
+ flwd_tuple4v4_t *nat_key, flwd_actual_ip_port_t *actual_ipport_net_order)
+{
+ /* ����dip, dport�ҵ���ʵ��������dip, dport, �滻�������ݰ�, Ȼ��洢��nat-htable */
+ return 0;
+}
+#endif
+
+
+
+/* TODO:
+ ��ֹ������, �ǶԳ�·������, ����S2C�����������C2S������ͬһ̨ת������,
+
+ Ҫ�����ӱ���ɢ��ȫ����ת������,
+
+ ��Ԫ��, dip+dport+sip, ��Ԫ����̫����,
+
+ sport����һ������ָ���㷨, ɨ����Ԫ������ж�sport.
+*/
+static int flwd_link_table_broadcast(int tid, flwd_nat_info_t *nat_info)
+{
+ /* TODO:
+ ��ֹ������, �ǶԳ�·������, ����S2C�����������C2S������ͬһ̨ת������,
+
+ Ҫ�����ӱ���ɢ��ȫ����ת������.
+ */
+ return 0;
+}
+
+
+/* ��ָ����Ϣ�洢��Դ�˿ڵ��ض��ֶ�, ��������IR�İ�����ʵ�ͻ��˵İ� */
+static void flwd_pkt_signature_hide_to_sport(
+ unsigned short pkt_signature, flwd_nat_info_t *nat_info)
+{
+ unsigned short sport_host_order;
+
+ pkt_signature &= (FLWD_UDP_SPORT_HASH_MASK >> 8);
+
+ if(0 == nat_info->outer_nat_tuple5.dir_reverse){
+ sport_host_order = ntohs(nat_info->outer_nat_tuple5.sport_net_order);
+ sport_host_order &= (~FLWD_UDP_SPORT_HASH_MASK); /* �����hash�ֶ� */
+ sport_host_order |= (pkt_signature << 8); /* hash�ֶ�������sport�� */
+ nat_info->outer_nat_tuple5.sport_net_order = htons(sport_host_order);
+ }else{
+ sport_host_order = ntohs(nat_info->outer_nat_tuple5.dport_net_order);
+ sport_host_order &= (~FLWD_UDP_SPORT_HASH_MASK); /* �����hash�ֶ� */
+ sport_host_order |= (pkt_signature << 8); /* hash�ֶ�������sport�� */
+ nat_info->outer_nat_tuple5.dport_net_order = htons(sport_host_order);
+ }
+
+ return;
+}
+
+
+/*
+ ѡ��Դ�˿���Ҫ��֤����ȥ���߳�id, ��Ӧ�������֮��, ���ܱ�����������ͬһ���߳�,
+ ������Ҫ���Զ��, �ҵ�һ�����ʵ�sport, ���ɷ��������ķ����㷨.
+
+ ��Ϊdip, dport�Dz��ܱ��, sipҲ�����ѡ�����ܱ�, ֻ����Դ�˿�����һЩtrick,
+ ���Ҷ����ͬ��������֮��, �������صIJ�ͬ�߳�֮���Ѿ�Ԥ�ȷ����˶˿ڷ�Χ,
+ ����һ����ԾIP��˵, �˿������������trick�ķ�Χ��С, ����׼ȷ�Ⱥܵ�!
+
+ ��ȡһ���²���:
+ 1,TCPЭ��, ʹ��SYN-ISNת������, ͨ��32bit��ISN����hash, ��Ϊָ��;
+ 2,DNSЭ��, ʹ��DNS-TRANSIDת������, ͨ��16bit��TRANSID��Ϊָ��, ��ͻ�ʱ�TCP_ISN���һЩ;
+ 3,����UDPЭ��, ѡ�����Ԫ��ʹ��maat_redisȫ����ɢ, ����Э����ܴ�����ʱ���⵼���װ���ʧ!
+*/
+static int flwd_acc_user_generate_pkt_signature(
+ int tid, flwd_nat_info_t *nat_info, flwd_raw_pkt_t *raw_pkt)
+{
+ const flwd_ipv4_hdr_t *flwd_iphdr = (flwd_ipv4_hdr_t *)raw_pkt->inner_ip_layer_hdr;
+ const flwd_udp_hdr_t *flwd_udphdr;
+ const flwd_tcp_hdr_t *flwd_tcphdr;
+ int canot_convert_pro;
+ unsigned int hash_val;
+ unsigned short pkt_signature;
+
+ if(FLWD_NAT_TYPE_SNAT != nat_info->nat_type){
+ return 0;
+ }
+
+ if(IPPROTO_TCP == flwd_iphdr->ip_p){
+ flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_iphdr + flwd_iphdr->ip_hl * 4);
+ assert(TH_SYN == flwd_tcphdr->th_flags);
+ canot_convert_pro = 0;
+ /* �˴�Ҫʹ��nat֮�����Ԫ��, ָ����Ϣ��Ҫ����ת������ʶ������internet�����ݰ� */
+ hash_val = flwd_tuple5_hash(&nat_info->outer_nat_tuple5, 1);
+ /*
+ TODO:
+ ����TCPЭ��, ʹ�ö˿�HASH�����ʽ��ͻ�ʽϸ�, �����޸�ISN�ķ�ʽ,
+ */
+#if 0
+ nat_info->signature_param = (long long)hash_val - (long long)ntohl(flwd_tcphdr->th_seq);
+#else
+ pkt_signature = hash_val % (FLWD_UDP_SPORT_HASH_MASK >> 8);
+#endif
+
+ }else if(IPPROTO_UDP == flwd_iphdr->ip_p){
+ /*
+ TODO,
+ ����UDPЭ��, ���ö˿�HASH����, ��ͻ��Ҳ�ϸ�, ������redisȫ����ɢ��Ԫ�鹦��,
+ IP���ú���ʵ�ͻ��˷���ͬһ��������, ���Ҷ˿ڻ����ɳ�ͻ�ļ��ʼ�С.
+ */
+ hash_val = flwd_tuple5_hash(&nat_info->outer_nat_tuple5, 1);
+ pkt_signature = hash_val % (FLWD_UDP_SPORT_HASH_MASK >> 8);
+ canot_convert_pro = 0;
+ }else{
+ canot_convert_pro = 1;
+ }
+
+ if(1 == canot_convert_pro){
+ /* TODO: ��ͨUDPЭ�鿿redisʵʱ��ɢ��Ԫ��, ʶ��Ӧ��� */
+ //flwd_link_table_broadcast(tid, nat_info);
+ }else{
+ flwd_pkt_signature_hide_to_sport(pkt_signature, nat_info);
+ }
+
+ return 0;
+}
+
+static flwd_terminal_proto_t flwd_access_proto_identify(flwd_raw_pkt_t *raw_pkt)
+{
+ flwd_terminal_proto_t flwd_pro = FLWD_TERMINAL_IP_LAYER;
+
+ /*
+ TODO:
+ ʶ��L2TP, PPTP���뷽ʽ�����ݰ�.
+
+ ���߿�������ʽ�ս�VPN, תΪ��IP��, ��ͬ��IP�������.
+ */
+
+ return flwd_pro;
+}
+
+
+
+/* �������شӿͻ��˷����հ�, ����ײ�ԭʼ���ݰ���ں��� */
+static int flwd_acc_user_pkt_input(flwd_device_handle_t *device_handle,
+ int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ int ret;
+
+ raw_pkt->terminal_proto = flwd_access_proto_identify(raw_pkt);
+ switch(raw_pkt->terminal_proto){
+ case FLWD_TERMINAL_IP_LAYER:
+ flwd_access_kernal_pkt_input(device_handle, tid, raw_pkt);
+ break;
+
+ case FLWD_TERMINAL_IP_L2TP:
+ /* TODO */
+ assert(0);
+ break;
+
+ case FLWD_TERMINAL_IP_PPTP:
+ /* TODO */
+ assert(0);
+ break;
+
+ default:
+ assert(0);
+ }
+
+ return 0;
+}
+
+/*
+ NAT��ַת��,
+ ����nat_info��, ����������Ԫ��, �滻���ݰ��е�IP�Ͷ˿�,
+ �����¼���У���.
+*/
+static int flwd_nat_set_new_addr_v4(flwd_topology_t topo_mode,
+ flwd_nat_type_t nat_type, const flwd_nat_info_t *nat_info, flwd_ipv4_hdr_t *flwd_ip4hdr)
+{
+ flwd_tcp_hdr_t *flwd_tcp_hdr;
+ flwd_udp_hdr_t *flwd_udp_hdr;
+ const flwd_tuple5_t *after_nat_addr;
+ struct ltsm_result ltsm_res;
+ unsigned int *tobe_modify_ip;
+ unsigned short *tobe_modify_port;
+ unsigned char tcp_flags = 0;
+
+ if(TOPO_ACC_LINK_USER == topo_mode){
+ /* C2I����, ��outer�ĵ�ַ, �滻��ǰ����Դip��Դ�˿� */
+ after_nat_addr = &nat_info->outer_nat_tuple5;
+ tobe_modify_ip = &flwd_ip4hdr->ip_src.s_addr;
+ if(IPPROTO_TCP == flwd_ip4hdr->ip_p){
+ flwd_tcp_hdr = (flwd_tcp_hdr_t *)((char *)flwd_ip4hdr + flwd_ip4hdr->ip_hl * 4);
+ tcp_flags = flwd_tcp_hdr->th_flags;
+ tobe_modify_port = &flwd_tcp_hdr->th_sport;
+ }else{
+ flwd_udp_hdr = (flwd_udp_hdr_t *)((char *)flwd_ip4hdr + flwd_ip4hdr->ip_hl * 4);
+ tobe_modify_port = &flwd_udp_hdr->uh_sport;
+ }
+ }else{
+ /* I2C����, ��inner�ĵ�ַ, �滻��ǰ����Ŀ��ip��Ŀ��˿� */
+ after_nat_addr = &nat_info->inner_nat_tuple5;
+ tobe_modify_ip = &flwd_ip4hdr->ip_dst.s_addr;
+ if(IPPROTO_TCP == flwd_ip4hdr->ip_p){
+ flwd_tcp_hdr = (flwd_tcp_hdr_t *)((char *)flwd_ip4hdr + flwd_ip4hdr->ip_hl * 4);
+ tcp_flags = flwd_tcp_hdr->th_flags;
+ tobe_modify_port = &flwd_tcp_hdr->th_dport;
+ }else{
+ flwd_udp_hdr = (flwd_udp_hdr_t *)((char *)flwd_ip4hdr + flwd_ip4hdr->ip_hl * 4);
+ tobe_modify_port = &flwd_udp_hdr->uh_dport;
+ }
+ }
+
+ /* Ϊ��hashֻ����һ��, key�ĵ�ַ�洢���Ǹ���sip>dip�Ľ������, Ҫ���ݴ洢��key�ĵ�ַ����, ѡ��������ԭʼ��ַ */
+ if(0 == after_nat_addr->dir_reverse){
+ *tobe_modify_ip = after_nat_addr->ippair_v4.sip_net_order;
+ *tobe_modify_port = after_nat_addr->sport_net_order;
+ }else{
+ *tobe_modify_ip = after_nat_addr->ippair_v4.dip_net_order;
+ *tobe_modify_port = after_nat_addr->dport_net_order;
+ }
+
+ if(IPPROTO_TCP == flwd_ip4hdr->ip_p){
+ flwd_sendpacket_do_checksum((char *)flwd_ip4hdr,
+ IPPROTO_TCP,
+ ntohs(flwd_ip4hdr->ip_len) - flwd_ip4hdr->ip_hl * 4); /* �Ӵ����ͷ����ʼ����ĩβ�ij��� */
+ }else{
+ flwd_sendpacket_do_checksum((char *)flwd_ip4hdr,
+ IPPROTO_UDP,
+ ntohs(flwd_ip4hdr->ip_len) - flwd_ip4hdr->ip_hl * 4); /* �Ӵ����ͷ����ʼ����ĩβ�ij��� */
+ }
+
+ flwd_sendpacket_do_checksum((char *)flwd_ip4hdr,
+ IPPROTO_IP,
+ sizeof(flwd_ipv4_hdr_t));
+
+#if FLWD_USE_LTSM_FOR_QUICK_CLOSE
+ unsigned char dir;
+ if(tcp_flags != 0){
+ if(FLWD_NAT_TYPE_SNAT == nat_info->nat_type){
+ if(TOPO_ACC_LINK_USER == topo_mode){
+ dir = LTSM_DIR_C2S; /* SNATģʽ, ��user���յ��Ŀ϶���client�˵İ� */
+ }else{
+ dir = LTSM_DIR_S2C;
+ }
+ }else{
+ if(TOPO_ACC_LINK_USER == topo_mode){
+ dir = LTSM_DIR_S2C;
+ }else{
+ dir = LTSM_DIR_C2S;
+ }
+ }
+
+ ltsm_res = ltsm_get_current_state(nat_info->ltsm_stat_handle, tcp_flags, dir);
+ }
+#endif
+
+ return (int)ltsm_res.fstate;
+}
+
+
+static int flwd_nat_set_new_addr_v6(flwd_topology_t topo_mode,
+ flwd_nat_type_t nat_type, const flwd_nat_info_t *nat_info,flwd_ipv6_hdr_t *flwd_ip6hdr)
+{
+ /* TODO, IPv6 NAT */
+ return -1;
+}
+
+
+/*
+ ����֮ǰ�Ѿ��洢��ת����, ��natת��
+ Ŀǰ���õIJ�����ֱ���޸�ԭʼ����IP��ַ�Ͷ˿�, �������, ����ÿ�ζ�malloc/memcpy/free����.
+*/
+static int flwd_do_nat(flwd_device_handle_t *device_handle,
+ flwd_nat_info_t *nat_info, flwd_raw_pkt_t *raw_pkt)
+{
+ int ret;
+
+ if(FLWD_IP_ADDR_TYPE_V4 == nat_info->outer_nat_tuple5.addr_type){
+ ret = flwd_nat_set_new_addr_v4(device_handle->io_para.topo_mode,
+ nat_info->nat_type, nat_info,
+ (flwd_ipv4_hdr_t *)raw_pkt->inner_ip_layer_hdr);
+ }else{
+ ret = flwd_nat_set_new_addr_v6(device_handle->io_para.topo_mode,
+ nat_info->nat_type, nat_info,
+ (flwd_ipv6_hdr_t *)raw_pkt->inner_ip_layer_hdr);
+ }
+
+ return ret;
+}
+
+static void *flwd_nat_table_search(void)
+{
+ /*
+ ת���������к�, �ὫSNAT��DNAT���ʹ洢��vxlan��ij���ֶΣ�
+
+ ����SNAT, C2S����Ĵ洢NAT�����Ԫ��, ��S2C����Ļ�����, �ٴβ���htable��ͬ��key�� �ָ�֮ǰ��ʵ�ͻ���IP��PORT����;
+
+ ����DNAT, ��һ��SYN��ɨ��IP���ò��Ա�, �ҵ�һ�����õ�RIP��RPORT, Ȼ��Ҳ�洢��htable,
+ ����������������İ�, ֱ�Ӻ�SNAT�ɸ���һ��htable, ����һ�μ��ɡ�
+ */
+ return 0;
+}
+
+
+static void * flwd_acc_to_fwd_pre_output(flwd_device_handle_t *rcv_device_handle,
+ flwd_device_handle_t *send_device_handle, int tid, flwd_nat_info_t *nat_info,
+ flwd_raw_pkt_t *raw_pkt, unsigned int out_opt)
+{
+ flwd_vxlan_hdr_t *outer_vxlan_hdr;
+ unsigned char *local_acc_gateway_mac = NULL ;
+ int ret;
+ flwd_ip_t ip_union;
+ char ip_str[64];
+ flwd_eth_hdr_t *inner_eth_hdr;
+
+ char *unsend_raw_data_ptr = rcv_device_handle->low_level_mbuff_mtod(raw_pkt->low_level_mbuff);
+ int unsend_raw_data_len = rcv_device_handle->low_level_mbuff_get_pkt_len(raw_pkt->low_level_mbuff);
+ void *send_mbuff = send_device_handle->low_level_mbuff_malloc(send_device_handle, tid, unsend_raw_data_len+FLWD_VXLAN_OUTER_PACKET_LEN);
+ char *send_buf_data_ptr;
+
+ /* �����վ���Ļ�����copy�������;���Ļ�����, �����߲���ģʽ���ܲ�һ��,
+ ����accessʹ��Э��ջģʽ, ��forwardʹ��marsioģʽ,
+ mbuff����ֱ�Ӹ���, ������һ��malloc/memcpy/free�Ĺ���.
+ */
+ send_device_handle->low_level_mbuff_data_append(send_mbuff, unsend_raw_data_ptr, unsend_raw_data_len);
+
+ /* ָ����ǰ�ƶ�, Ԥ��vxlan���ռ� */
+ send_buf_data_ptr = (char *)send_device_handle->low_level_mbuff_data_forward(send_mbuff, FLWD_VXLAN_OUTER_PACKET_LEN);
+
+ /* ����ײ�vxlan��Ϣ, ���迼�Ƿ������, ��Ϊ�����ڲ���Ԫ��hash����, vxlan����ַ����·��Ѱַ���� */
+
+#if FLWD_NO_ACTIVE_ARP_QUERY
+ local_acc_gateway_mac = send_device_handle->io_para.local_mac_addr;
+ unsigned char remote_fwd_gateway_mac[6] = {0x0c, 0xc4,0x7a,0x14,0x6f,0x5a}; /* 10.0.6.203 */
+ flwd_sendpacket_build_ethernet(ETH_P_IP, local_acc_gateway_mac, remote_fwd_gateway_mac, send_buf_data_ptr);
+#else
+ if(send_device_handle->io_para.cap_mode != CAP_MODEL_SOCKET){ /* ��socketģʽ����Ҫ����vxlan����ethernet�� */
+ local_acc_gateway_mac = send_device_handle->io_para.local_mac_addr;
+
+ ip_union.addr_type = FLWD_IP_ADDR_TYPE_V4;
+ ip_union.addr_ipv4 = nat_info->flwd_route_info.next_gateway_ip_net;
+
+ if(memcmp(nat_info->flwd_route_info.next_gateway_mac, flwd_global_val.zero_mac_addr, 6) == 0){
+ /* �˴�������MAC���浽nat_info, ����ÿ�ζ���arp�� */
+ ret = flwd_arp_table_query(nat_info->tid, &ip_union, send_device_handle, nat_info->flwd_route_info.next_gateway_mac);
+ if(ret < 0){
+ send_device_handle->low_level_mbuff_free(send_device_handle, tid, send_mbuff);
+ flwd_log(30, "arp query %s, but not found!\n", flwd_ipt_ntop_r(&ip_union, ip_str, 64));
+ return NULL;
+ }
+ }
+
+ /* ���ݻ�ԾIP�IJ���ʱ��gdevIP, ��ѯGDEV��MAC, ����ethernet header */
+ unsigned char *remote_fwd_gateway_mac = nat_info->flwd_route_info.next_gateway_mac;
+ flwd_sendpacket_build_ethernet(ETH_P_IP, local_acc_gateway_mac, remote_fwd_gateway_mac, send_buf_data_ptr);
+ }
+
+#endif
+
+ /* NOTE, ��ʹ��socketģʽ, ����Ҫ����ײ�vxlanԭʼ��, ��DIP, PORT���ܶ���һ��, ����Щֵ���Ƿ�װ�����ݰ���, ��dl_io_send�Ӱ���ȡ */
+#if FLWD_NO_GDEV_ENV
+ flwd_sendpacket_build_ipv4(unsend_raw_data_len + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t), /* �ڲ�ԭʼ�� + UDP��ͷ + vxlanͷ */
+ 0,
+ 0x1234,
+ 0,
+ 64,
+ IPPROTO_UDP,
+ send_device_handle->io_para.device_ip_net_order,
+ nat_info->flwd_route_info.next_gateway_ip_net,
+ NULL,
+ 0,
+ (char *)send_buf_data_ptr + sizeof(flwd_eth_hdr_t));
+#else
+ flwd_sendpacket_build_ipv4(unsend_raw_data_len + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t), /* �ڲ�ԭʼ�� + UDP��ͷ + vxlanͷ */
+ 0,
+ 0x1234,
+ 0,
+ 64,
+ IPPROTO_UDP,
+ 0x0100007F, /* ����socket */
+ 0x0100007F, /* ����socket */
+ NULL,
+ 0,
+ (char *)send_buf_data_ptr + sizeof(flwd_eth_hdr_t));
+#endif
+
+ flwd_sendpacket_build_udp(unsend_raw_data_len + sizeof(flwd_vxlan_hdr_t),
+ htons(50000 + tid), /* TODO, �˴���sport�����ڲ��sport, �ڲ�sport��ȫ��ʶ��ij���������ص�, vxlan��sport�������� */
+ htons(60000 + tid),
+ NULL,
+ 0,
+ send_buf_data_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t));
+
+ if(CAP_MODEL_SOCKET != send_device_handle->io_para.cap_mode){ /* socketģʽ�ײ���Э��ջ��װ, У�����Э��ջʵ�� */
+ flwd_sendpacket_do_checksum((char *)send_buf_data_ptr + sizeof(flwd_eth_hdr_t),
+ IPPROTO_IP,
+ sizeof(flwd_ipv4_hdr_t));
+ }
+
+ outer_vxlan_hdr = (flwd_vxlan_hdr_t *)(send_buf_data_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t));
+ memset(outer_vxlan_hdr, 0, sizeof(flwd_vxlan_hdr_t));
+ outer_vxlan_hdr->link_id = nat_info->flwd_route_info.gdev_args.link_id;
+ outer_vxlan_hdr->link_layer_type = 0; /* 0:ethernet; */
+ outer_vxlan_hdr->dir = nat_info->flwd_route_info.gdev_args.this_ip_as_sip_route_dir;
+ if(FLWD_OUTOPT_FIRST_PKT == (out_opt & FLWD_OUTOPT_FIRST_PKT)){
+ outer_vxlan_hdr->first_pkt_per_stream = 1;
+ }
+
+ inner_eth_hdr = (flwd_eth_hdr_t *)(send_buf_data_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t));
+ memcpy(inner_eth_hdr->h_source, nat_info->flwd_route_info.gdev_args.inner_raw_smac, 6);
+ memcpy(inner_eth_hdr->h_dest , nat_info->flwd_route_info.gdev_args.inner_raw_dmac, 6);
+
+ if(FLWD_IP_ADDR_TYPE_V4 == nat_info->inner_nat_tuple5.addr_type){
+ inner_eth_hdr->h_proto = htons(ETH_P_IP);
+ }else{
+ inner_eth_hdr->h_proto = htons(ETH_P_IPV6);
+ }
+
+ return send_mbuff;
+}
+
+static void * flwd_acc_to_user_pre_output(flwd_device_handle_t *rcv_device_handle,
+ flwd_device_handle_t *send_device_handle, int tid, flwd_nat_info_t *nat_info,
+ flwd_raw_pkt_t *raw_pkt, unsigned int out_opt)
+{
+ flwd_vxlan_hdr_t *outer_vxlan_dr;
+
+ const char *unsend_raw_data_ptr = raw_pkt->inner_pkt_data; /* ��ָ����flwd_acc_fwd_pkt_input()����, �Ѿ�ָ�����ڲ�ethernetͷ�� */
+ int unsend_raw_data_len = raw_pkt->inner_pkt_len;
+ void *send_mbuff = send_device_handle->low_level_mbuff_malloc(send_device_handle, tid, unsend_raw_data_len + FLWD_VXLAN_OUTER_PACKET_LEN);
+ char *send_buf_data_ptr;
+
+ /* �����վ���Ļ�����copy�������;���Ļ�����, �����߲���ģʽ���ܲ�һ��, ����ֱ�Ӹ���, ������һ��malloc/memcpy/free�Ĺ��� */
+ send_buf_data_ptr = send_device_handle->low_level_mbuff_data_append(send_mbuff, unsend_raw_data_ptr, unsend_raw_data_len);
+
+#if FLWD_NO_ACTIVE_ARP_QUERY
+ /* û��ARP��̬��ѯ�Ĺ���ʱ, �ֹ����²����ն˵�mac */
+ unsigned char *local_acc_gateway_mac = send_device_handle->io_para.local_mac_addr;
+ unsigned char *remote_user_mac = nat_info->flwd_route_info.inner_terminal_mac;
+
+ flwd_sendpacket_build_ethernet(ETH_P_IP, local_acc_gateway_mac, remote_user_mac, send_buf_data_ptr);
+#else
+ /* û��ARP��̬��ѯ�Ĺ���ʱ, �ֹ����²����ն˵�mac */
+ unsigned char *local_acc_gateway_mac = send_device_handle->io_para.local_mac_addr;
+ unsigned char *remote_user_mac = nat_info->flwd_route_info.inner_terminal_mac;
+
+ flwd_sendpacket_build_ethernet(ETH_P_IP, local_acc_gateway_mac, remote_user_mac, send_buf_data_ptr);
+#endif
+
+ return send_mbuff;
+}
+
+
+/*
+ TODO:
+ ��ϵͳ����������������ʵ��L2TP, PPTP��������,
+ ��Iptables ��ppp�������һ������ָ��(�ض���)��һ��tap�豸,
+ ����, tap�豸�Ķ�ȡ��(��������), ���ܿ��������ڲ���ip��,
+ �յ�ip�����acc-userһ���Ĵ�������.
+
+ ����:
+ acc-userֻ��һ��io_handle, Ŀǰ��pcap, marsio, socket, ��tap,
+ ������pcap��tap�ľ�����Բ�һ��,
+
+ �����ʽ:
+ 1, һ��Flowood_IO���(�ĸ�����, acc-user, acc-fwd, fwd-acc, fwd-gdev), �ɶ�Ӧ�������IO���,
+ ��acc-user�����IO�����������������IO���, ��������ͬ�Ľ��뷽ʽ: pcap, l2tp_tap, pptp_tap,
+ �����������Ľ����ij�;
+
+ 2, ����Ǹ���һ������, ������������Ƕ��, ��ʵ�ʴ�һ����������;
+ ��acc-user, acc-fwd����һ���������ӵ�������,
+ Flowood���������, ��ʵ��������һ��, ��ʱӦ�ÿ���ͬ��IP��������,
+ ��һ���������IP��ַ, �����ݰ���dip�����ĸ���acc-user�İ�, �ĸ���acc-fwd�İ�.
+
+*/
+
+static int flwd_access_output(flwd_device_handle_t *rcv_device_handle, int tid,
+ flwd_nat_info_t *nat_info, flwd_raw_pkt_t *raw_pkt, unsigned int out_opt)
+{
+ int ret;
+ flwd_device_handle_t *send_device_handle;
+ void *send_mbuff ;
+ const char *send_actual_ptr;
+ char debug_outer_tuple4[128];
+
+ /*
+ TODO,
+
+ ACC��USERת������ʱ, �������ͨIPЭ��ջ, ����ͨ��low_level_io_send()ֱ�ӽ�������ȥ,
+ ���п��ܻ���PPTP����, ��ʱ�����ݰ������ڲ����һ����, ���PPP��װ��Ҫ��VPN�������,
+ ��Ҫע�����������, ������ͨ���ײ�IO�ӿ�ֱ�ӷ��ͳ�����.
+
+ Ӧ�������ֵײ������ӿ�, ���pcap, marsio, socket��ϵͳ��ʽ,
+ �߼��ӿ�, ��һ������������IP, ���������߼�����,
+ ������L2TP, PPTP������, ��ԭʼ�������յ�PPP�İ���, ���ջ�������ڲ�IP��,
+
+ ��������߼�����һ�Զ�Ĺ�ϵ, ��ʹ����һ���ӿ�, Ҳ���������һ���߼���,
+ flowood������߼������ͨ��, ����ֱ�Ӷ�������.
+ */
+
+ if(TOPO_ACC_LINK_USER == rcv_device_handle->io_para.topo_mode){
+ send_device_handle = &flwd_global_val.global_io_handle[TOPO_ACC_LINK_FWD];
+ send_mbuff = flwd_acc_to_fwd_pre_output(rcv_device_handle, send_device_handle, tid, nat_info, raw_pkt, out_opt);
+ if(NULL == send_mbuff){
+ return -1;
+ }
+ ret = send_device_handle->low_level_send(send_device_handle, tid, send_mbuff);
+ if(ret < 0){
+ send_actual_ptr = (char *)rcv_device_handle->low_level_mbuff_mtod(send_mbuff);
+ flwd_log(30, "ACC: send pkt to forward gateway error! inner_tuple4 is:%s, outer_tuple4 is:%s\n",
+ flwd_debug_print_tuple4_detail(send_actual_ptr+FLWD_VXLAN_OUTER_PACKET_LEN+sizeof(flwd_eth_hdr_t), tid),
+ flwd_debug_print_tuple4_detail_r(send_actual_ptr + sizeof(flwd_eth_hdr_t), debug_outer_tuple4, 128));
+ }else{
+ if(flwd_cfg_val.flwd_log_level <= 10){
+ send_actual_ptr = (char *)rcv_device_handle->low_level_mbuff_mtod(send_mbuff);
+ flwd_log(10, "ACC: send pkt to forward gateway succ, inner_tuple4 is:%s, outer_tuple4 is:%s\n",
+ flwd_debug_print_tuple4_detail(send_actual_ptr+FLWD_VXLAN_OUTER_PACKET_LEN+sizeof(flwd_eth_hdr_t), tid),
+ flwd_debug_print_tuple4_detail_r(send_actual_ptr + sizeof(flwd_eth_hdr_t), debug_outer_tuple4, 128));
+ }
+ }
+
+ }else{
+ send_device_handle = &flwd_global_val.global_io_handle[TOPO_ACC_LINK_USER];
+ send_mbuff = flwd_acc_to_user_pre_output(rcv_device_handle, send_device_handle, tid, nat_info, raw_pkt, out_opt);
+ ret = send_device_handle->low_level_send(send_device_handle, tid, send_mbuff);
+ if(ret < 0){
+ send_actual_ptr = (char *)rcv_device_handle->low_level_mbuff_mtod(send_mbuff);
+ flwd_log(30, "ACC: send pkt to user client error! tuple4 is:%s\n",
+ flwd_debug_print_tuple4_detail(send_actual_ptr+sizeof(flwd_eth_hdr_t), tid));
+ }else{
+ if(flwd_cfg_val.flwd_log_level <= 10){
+ send_actual_ptr = (char *)rcv_device_handle->low_level_mbuff_mtod(send_mbuff);
+ flwd_log(10, "ACC: send pkt to user client succ! tuple4 is:%s\n",
+ flwd_debug_print_tuple4_detail(send_actual_ptr+sizeof(flwd_eth_hdr_t), tid));
+
+ }
+ }
+ }
+
+ send_device_handle->low_level_mbuff_free_after_send(send_device_handle, tid, send_mbuff);
+
+ return ret;
+}
+
+
+/*
+ ���ӽ�����, �ͷ�ռ�û�ԾIP��Դ�˿�.
+*/
+static void flwd_sport_recycle(flwd_nat_info_t *nat_info)
+{
+ /* ����nat����, snat����outer->tuple5��sip, ����ʵ����ԴIP;
+ dnatû�ж��������Դ, ֻ�Ǽ򵥵Ľ�virtual_dip:virtual_dport�ij���real_dip:real_dport.
+ */
+ MESA_list_count_t *usable_sport_queue_head;
+ MESA_list_count_t *recycle_node;
+ unsigned char *ip_key;
+ unsigned int ip_key_size;
+ MESA_htable_handle act_ip_htable;
+ int tid = nat_info->tid;
+ const flwd_tuple5_t *recycle_tuple5;
+ unsigned short recycle_sport;
+ char ip_str[64];
+
+ if(FLWD_NAT_TYPE_DNAT == nat_info->nat_type){
+ return; /* nothing to do */
+ }
+
+ if(FLWD_NAT_TYPE_SNAT == nat_info->nat_type){
+ recycle_tuple5 = &nat_info->outer_nat_tuple5;
+ }
+
+ if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == nat_info->inner_nat_tuple5.addr_type)){
+ if(FLWD_ACT_IP_DYNAMIC == nat_info->act_ip_origin){
+ act_ip_htable = flwd_thread_val[tid].flwd_ip_pool_dynamic_htable[FLWD_IP_ADDR_TYPE_V4][nat_info->act_ip_region];
+ }else{
+ act_ip_htable = flwd_thread_val[tid].flwd_ip_pool_static_htable[FLWD_IP_ADDR_TYPE_V4][nat_info->act_ip_region];
+ }
+
+ if(recycle_tuple5->dir_reverse){
+ ip_key = (unsigned char *)&recycle_tuple5->ippair_v4.dip_net_order;
+ recycle_sport = recycle_tuple5->dport_net_order;
+ }else{
+ ip_key = (unsigned char *)&recycle_tuple5->ippair_v4.sip_net_order;
+ recycle_sport = recycle_tuple5->sport_net_order;
+ }
+ ip_key_size = sizeof(int);
+ }else{ /* IPv6 */
+ if(FLWD_ACT_IP_DYNAMIC == nat_info->act_ip_origin){
+ act_ip_htable = flwd_thread_val[tid].flwd_ip_pool_dynamic_htable[FLWD_IP_ADDR_TYPE_V6][nat_info->act_ip_region];
+ }else{
+ act_ip_htable = flwd_thread_val[tid].flwd_ip_pool_static_htable[FLWD_IP_ADDR_TYPE_V6][nat_info->act_ip_region];
+ }
+
+ if(recycle_tuple5->dir_reverse){
+ ip_key = (unsigned char *)&recycle_tuple5->ippair_v6->dip_net_order;
+ recycle_sport = recycle_tuple5->dport_net_order;
+ }else{
+ ip_key = (unsigned char *)&recycle_tuple5->ippair_v6->sip_net_order;
+ recycle_sport = recycle_tuple5->sport_net_order;
+ }
+ ip_key_size = sizeof(struct in6_addr);
+ }
+
+ if(sizeof(int) == ip_key_size){
+ inet_ntop(AF_INET, ip_key, ip_str, 64);
+ }else{
+ inet_ntop(AF_INET6, ip_key, ip_str, 64);
+ }
+
+ pthread_rwlock_wrlock(&flwd_thread_val[tid].flwd_ip_pool_static_rwlock);
+
+ flwd_active_ip_t *flwd_active_ip = (flwd_active_ip_t *)flwd_ip_pool_search(nat_info->act_ip_origin, act_ip_htable, ip_key, ip_key_size);
+ if(NULL == flwd_active_ip){
+ /* NOTE: �������ڼ�˻�ԾIP�Ѿ���ʱ��maat_callback�Ƴ�, Ҳ�Ͳ��ػ��ն˿�, ֱ�ӷ��ؼ��� */
+ flwd_log(20, "ACC:sport %u recycle, but active ip:%s is not exist!\n", recycle_sport, ip_str);
+ goto done;
+ }
+
+ if(IPPROTO_TCP == nat_info->inner_nat_tuple5.protocol){ /* TCP, UDP������ */
+ usable_sport_queue_head = &flwd_active_ip->usable_tcp_sport_list_head;
+ }else{
+ usable_sport_queue_head = &flwd_active_ip->usable_udp_sport_list_head;
+ }
+
+ /* NOTE: ȡ���ö˿�ʱ�ֳ�free��MESA_list_count_t�����ṹ, �˴�Ҳ���ֳ�malloc */
+ recycle_node = (MESA_list_count_t *)malloc(sizeof(MESA_list_count_t));
+ memcpy(&recycle_node->quiddity, &recycle_sport, sizeof(short));
+ /* �˴�ʹ��MESA_list_count_add_tail, ����head->pre, ���ʹ�� */
+ MESA_list_count_add_tail(usable_sport_queue_head, recycle_node);
+
+done:
+ pthread_rwlock_unlock(&flwd_thread_val[tid].flwd_ip_pool_static_rwlock);
+
+ flwd_log(10, "ACC:sport recycle, active_ip:%s, port:%u\n", ip_str, recycle_sport);
+
+ return;
+}
+
+
+static void flwd_access_nat_htable_data_free(void *data)
+{
+ flwd_nat_info_t *nat_info = (flwd_nat_info_t *)data;
+
+ if(--nat_info->reference > 0){
+ /* ����key����ͬһ��nat_info, ɾ��ʱ����double free, ����reference���� */
+ return;
+ }
+
+ flwd_sport_recycle(nat_info);
+
+ if(FLWD_IP_ADDR_TYPE_V6 == nat_info->inner_nat_tuple5.addr_type ){
+ flwd_free(nat_info->tid, nat_info->inner_nat_tuple5.ippair_v6);
+ }
+
+ if(FLWD_IP_ADDR_TYPE_V6 == nat_info->outer_nat_tuple5.addr_type ){
+ flwd_free(nat_info->tid, nat_info->outer_nat_tuple5.ippair_v6);
+ }
+
+#if FLWD_USE_LTSM_FOR_QUICK_CLOSE
+ ltsm_destroy_handle(nat_info->ltsm_stat_handle);
+#endif
+
+ flwd_free(nat_info->tid, data);
+}
+
+static int flwd_access_nat_htable_data_expire_notify(
+ void *data, int eliminate_type)
+{
+ char str_tmp[256];
+ flwd_nat_info_t *nat_info = (flwd_nat_info_t *)data;
+
+ if(1 == nat_info->reference){ /* ��Ϊͬʱ������key����, ֻ���һ�μ�¼��־, �����д����һ������־ */
+ flwd_log(10, "pre-nat-tuple4 %s expire!\n",
+ flwd_tuple5_ntop_r(&nat_info->inner_nat_tuple5, str_tmp, 256));
+ }
+
+ return 1;
+}
+
+
+
+/*
+ natת����������, ��һ�δ���nat_infoʱ������,
+ �洢·��ת�������Ϣ, ����ÿ��ת��ʱ����ѯһ��.
+*/
+static int flwd_save_session_route_info(flwd_nat_info_t *nat_info,
+ flwd_raw_pkt_t *raw_pkt, flwd_active_ip_port_args_t *usable_active_ipport_args)
+{
+ const flwd_eth_hdr_t *ehdr = (flwd_eth_hdr_t *)raw_pkt->outer_pkt_data;
+ int ret;
+
+ if(FLWD_NAT_TYPE_SNAT == nat_info->nat_type){
+ /* user�ն˵�MAC���ò�ѯ, ֱ��ʹ�õ�ǰ������mac�洢�������� */
+ memcpy(nat_info->flwd_route_info.inner_terminal_mac, ehdr->h_source, ETH_ALEN);
+ /*
+ TODO:
+ ��εõ���һ��ת�����ص�IP, ��ת������IP?
+ ������ͬһ���ֵ�������豸������ͨ��, ��ѡһ���Ϳ���,
+ ��������ɵ�����,
+ �����֪��GDEV�ķ����㷨�����.
+ */
+#if 0
+ nat_info->flwd_route_info.next_gateway_ip_net = flwd_search_fwd_ip_by_gdev_ip(usable_active_ipport_args->gdev_args.gdev_ip_net_order);
+#else
+ /* TODO, ��̨����, ��д��, ʹ�ñ��ػػ� */
+ inet_pton(AF_INET, "127.0.0.1", &nat_info->flwd_route_info.next_gateway_ip_net);
+#endif
+
+ memcpy(&nat_info->flwd_route_info.gdev_args,
+ &usable_active_ipport_args->gdev_args,
+ sizeof(flwd_gdev_associated_args_t));
+ }else{
+ /* TODO, DNAT */
+ abort();
+ }
+
+ return 0;
+}
+
+
+/*
+ NOTE:
+
+ HASH����ʱ,
+ ��ΪSNAT->C2S����, SNAT->S2C����, DNAT->C2S����, DNAT->S2C����,
+ ��������ĵ�ַ��ͬ,
+ ����, ����һ�����ӵ��ڲ���ַ���ⲿ��ַ��˵, Ҫ��������key, ָ��ͬһ��nat_info.
+
+ hash����ʱ, ����ͬһ��nat_info, ʹ��������ͬ��key����.
+
+ ����:
+ 192.168.10.100:12345->8.8.8.8:53����һ��DNS��ѯ,
+ ��NAT���غ�����:
+ 202.43.148.189:34567->8.8.8.8:53,
+
+ Ҫ������������ͬ����Ԫ��ֱ���Ϊkey, �����ҵ�ͬһ��htable���data, ��nat_info.
+*/
+static int flwd_new_nat_session_sotre(int tid, flwd_nat_info_t *nat_info)
+{
+ int ret;
+ char inner_str[256], outer_str[256];
+
+ ret = MESA_htable_add(flwd_thread_val[tid].nat_info_table,
+ (unsigned char *)&nat_info->inner_nat_tuple5,
+ sizeof(flwd_tuple5_t),
+ nat_info);
+ if(ret < 0){
+ flwd_log(30, "save nat session error, %s!\n",
+ flwd_tuple5_ntop_r(&nat_info->inner_nat_tuple5, inner_str, 256));
+ nat_info->reference = 1;
+ flwd_access_nat_htable_data_free(nat_info);
+ return -1;
+ }
+ nat_info->reference++;
+
+ ret = MESA_htable_add(flwd_thread_val[tid].nat_info_table,
+ (unsigned char *)&nat_info->outer_nat_tuple5,
+ sizeof(flwd_tuple5_t),
+ nat_info);
+ if(ret < 0){
+ nat_info->reference = 1;
+ flwd_log(30, "save nat session error, %s!\n",
+ flwd_tuple5_ntop_r(&nat_info->outer_nat_tuple5, outer_str, 256));
+ /* NOTE: ����ʧ��, �˴�Ҫʹ��inner��key, ��Ϊouter����ʧ�� */
+ MESA_htable_del(flwd_thread_val[tid].nat_info_table,
+ (unsigned char *)&nat_info->inner_nat_tuple5,
+ sizeof(flwd_tuple5_t),
+ NULL);
+ return -1;
+ }
+ nat_info->reference++;
+
+ return 0;
+}
+
+
+static inline flwd_nat_info_t *flwd_create_new_nat_info_v4(int tid,
+ flwd_nat_type_t nat_type, flwd_tuple5_t *inner_nat_key,
+ flwd_active_ip_port_args_t *usable_active_ipport_args, flwd_raw_pkt_t *raw_pkt)
+{
+ flwd_nat_info_t *nat_info = (flwd_nat_info_t *)flwd_calloc(tid, 1, sizeof(flwd_nat_info_t));
+ flwd_tuple5_t *opposite_tuple5;
+ int differ;
+ unsigned int outer_actual_dip_net_order; /* �ͻ���ȥ����ʵ��Ŀ��IP, inner��outer��һ����, ����key�Ĵ洢λ��, ��sip,dip�Ĵ�С��ϵ���ܲ�һ�� */
+ unsigned int outer_actual_dport_net_order; /* �ͻ���ȥ����ʵ��Ŀ��˿�, inner��outer��һ����, ����key�Ĵ洢λ��, ��sip,dip�Ĵ�С��ϵ���ܲ�һ�� */
+
+ nat_info->tid = tid; /* ��Ҫ����htable�ص������ڲ���tid�������� */
+ nat_info->nat_type = nat_type;
+
+ if(FLWD_NAT_TYPE_SNAT == nat_type){
+ /************************** ���� inner tuple5 **************************/
+ memcpy(&nat_info->inner_nat_tuple5, inner_nat_key, sizeof(flwd_tuple5_t)); /* snat��inner tuple5ֱ��copy */
+
+
+ /*************************** ����outer tuple5 **************************/
+ opposite_tuple5 = &nat_info->outer_nat_tuple5;
+
+ if(inner_nat_key->dir_reverse){
+ outer_actual_dip_net_order = inner_nat_key->ippair_v4.sip_net_order;
+ outer_actual_dport_net_order = inner_nat_key->sport_net_order;
+ }else{
+ outer_actual_dip_net_order = inner_nat_key->ippair_v4.dip_net_order;
+ outer_actual_dport_net_order = inner_nat_key->dport_net_order;
+ }
+
+ /* NOTE: �����޷��������Ƚϴ�С, һ��Ҫֱ�ӱȽ�, ������ c = a - b; if(c < 0)�ķ�ʽ!!! */
+ if(usable_active_ipport_args->act_sip_net_order.addr_ipv4 > outer_actual_dip_net_order){
+ /* �ⲿ��ַ����ʵԴIP�Ǹ�ѡ��Ļ�ԾIP, ��ʵĿ��IP���ǵ�ǰinner_key��Ŀ��ip */
+ opposite_tuple5->ippair_v4.sip_net_order = usable_active_ipport_args->act_sip_net_order.addr_ipv4;
+ opposite_tuple5->ippair_v4.dip_net_order = outer_actual_dip_net_order;
+ opposite_tuple5->sport_net_order = usable_active_ipport_args->act_sport_net_order;
+ opposite_tuple5->dport_net_order = outer_actual_dport_net_order;
+
+ opposite_tuple5->dir_reverse = 0; /* �洢��key����ʵ��Ԫ���ַ��һ���� */
+ }else if(usable_active_ipport_args->act_sip_net_order.addr_ipv4 < outer_actual_dip_net_order){
+ opposite_tuple5->ippair_v4.sip_net_order = outer_actual_dip_net_order;
+ opposite_tuple5->ippair_v4.dip_net_order = usable_active_ipport_args->act_sip_net_order.addr_ipv4;
+ opposite_tuple5->sport_net_order = outer_actual_dport_net_order;
+ opposite_tuple5->dport_net_order = usable_active_ipport_args->act_sport_net_order;
+
+ opposite_tuple5->dir_reverse = 1; /* �洢��key����ʵ��Ԫ���ַ���෴�� */
+ }else{
+ /* inner��outer��IP��ַ��ͬ, ��������IP����ϵͳ���Dz����ܵ�!!! */
+ abort();
+ }
+
+ opposite_tuple5->addr_type = inner_nat_key->addr_type; /* TODO, Ԥ��6to4��ַת������?? */
+ opposite_tuple5->protocol = inner_nat_key->protocol;
+
+ /* TODO, ����ѡ��Ļ�ԾIP, �������, ȷ��Ӧ�ô��ĸ�FWD���� */
+ ////nat_info->next_hop_ip_net_order = flwd_search_fwd_ip_by_gdev_ip(usable_active_ipport_args->related_gdev_ip_net_order);
+ }else{
+#if FLWD_SUPPORT_DNAT
+ /* TODO,
+ DNATֻ����滻dip, dport����, ���ÿ�����ô��ѡ�˿�, �˿ڸ�������,
+ ��Ϊ����һ���������, ��ʵԴIP,Դport�Ѿ�������������Э��ջ��֤�޳�ͻ��.
+ */
+ assert(0);
+#endif
+ }
+
+ flwd_save_session_route_info(nat_info, raw_pkt, usable_active_ipport_args);
+
+ return nat_info;
+}
+
+
+static inline flwd_nat_info_t *flwd_create_new_nat_info_v6(int tid,
+ flwd_nat_type_t nat_type, flwd_tuple5_t *inner_tuple5_v6,
+ flwd_active_ip_port_args_t *usable_active_ipport_args, flwd_raw_pkt_t *raw_pkt)
+{
+ flwd_nat_info_t *nat_info = (flwd_nat_info_t *)flwd_calloc(tid, 1, sizeof(flwd_nat_info_t));
+ flwd_tuple5_t *opposite_tuple5;
+ int differ;
+ struct in6_addr outer_actual_dip_net_order; /* �ͻ���ȥ����ʵ��Ŀ��IP, inner��outer��һ����, ����key�Ĵ洢λ��, ��sip,dip�Ĵ�С��ϵ���ܲ�һ�� */
+ unsigned int outer_actual_dport_net_order; /* �ͻ���ȥ����ʵ��Ŀ��˿�, inner��outer��һ����, ����key�Ĵ洢λ��, ��sip,dip�Ĵ�С��ϵ���ܲ�һ�� */
+
+ nat_info->tid = tid; /* ��Ҫ����htable�ص������ڲ���tid�������� */
+ nat_info->nat_type = nat_type;
+
+ nat_info->inner_nat_tuple5.ippair_v6 = (flwd_ippair_v6_t *)flwd_malloc(tid, sizeof(flwd_ippair_v6_t));
+ nat_info->outer_nat_tuple5.ippair_v6 = (flwd_ippair_v6_t *)flwd_malloc(tid, sizeof(flwd_ippair_v6_t));
+
+ if(FLWD_NAT_TYPE_SNAT == nat_type){
+ /********* ���� inner tuple5 ******/
+ memcpy(&nat_info->inner_nat_tuple5, inner_tuple5_v6, sizeof(flwd_tuple5_t)); /* snat��inner tuple5ֱ��copy */
+ memcpy(nat_info->inner_nat_tuple5.ippair_v6, inner_tuple5_v6->ippair_v6, sizeof(flwd_ippair_v6_t));
+
+ opposite_tuple5 = &nat_info->outer_nat_tuple5;
+ /********* ����outer tuple5 ******/
+
+ if(inner_tuple5_v6->dir_reverse){
+ outer_actual_dip_net_order = inner_tuple5_v6->ippair_v6->sip_net_order;
+ outer_actual_dport_net_order = inner_tuple5_v6->sport_net_order;
+ }else{
+ outer_actual_dip_net_order = inner_tuple5_v6->ippair_v6->dip_net_order;
+ outer_actual_dport_net_order = inner_tuple5_v6->dport_net_order;
+ }
+
+ differ = memcmp(&usable_active_ipport_args->act_sip_net_order.addr_ipv6, &outer_actual_dip_net_order, sizeof(struct in6_addr)) ;
+ if(differ > 0){ /* �ⲿ��ַ����ʵԴIP�Ǹ�ѡ��Ļ�ԾIP, ��ʵĿ��IP���ǵ�ǰinner_key��Ŀ��ip */
+ memcpy(&opposite_tuple5->ippair_v6->sip_net_order, &usable_active_ipport_args->act_sip_net_order.addr_ipv6, sizeof(struct in6_addr));
+ memcpy(&opposite_tuple5->ippair_v6->dip_net_order, &outer_actual_dip_net_order, sizeof(struct in6_addr));
+ opposite_tuple5->sport_net_order = usable_active_ipport_args->act_sport_net_order;
+ opposite_tuple5->dport_net_order = outer_actual_dport_net_order;
+
+ opposite_tuple5->dir_reverse = 0; /* �洢��key����ʵ��Ԫ���ַ��һ���� */
+ }else if(differ < 0){
+ memcpy(&opposite_tuple5->ippair_v6->sip_net_order, &outer_actual_dip_net_order, sizeof(struct in6_addr));
+ memcpy(&opposite_tuple5->ippair_v6->dip_net_order, &usable_active_ipport_args->act_sip_net_order.addr_ipv6, sizeof(struct in6_addr));
+ opposite_tuple5->sport_net_order = outer_actual_dport_net_order;
+ opposite_tuple5->dport_net_order = usable_active_ipport_args->act_sport_net_order;
+
+ opposite_tuple5->dir_reverse = 1; /* �洢��key����ʵ��Ԫ���ַ���෴�� */
+ }else{
+ /* inner��outer��IP��ַ��ͬ, ��������flowoodϵͳ���Dz����ܵ�!!! */
+ abort();
+ }
+
+ opposite_tuple5->addr_type = inner_tuple5_v6->addr_type; /* TODO, Ԥ��6to4��ַת������, �ⲿ��ַ�����Ǹ��ݲ��Եõ�, ��һ���ǹ̶���ipv4תipv4 */
+ opposite_tuple5->protocol = inner_tuple5_v6->protocol;
+
+ ////nat_info->next_hop_ip_net_order = flwd_search_fwd_ip_by_gdev_ip(usable_active_ipport_args->related_gdev_ip_net_order); /* TODO, ����ѡ��Ļ�ԾIP, �������, ȷ��Ӧ�ô��ĸ�FWD���� */
+
+ }else{
+#if FLWD_SUPPORT_DNAT
+ assert(0);
+#endif
+ }
+
+ flwd_save_session_route_info(nat_info, raw_pkt, usable_active_ipport_args);
+
+ return nat_info;
+}
+
+
+
+static flwd_nat_info_t *flwd_create_new_nat_info(int tid,
+ flwd_nat_type_t nat_type, flwd_tuple5_t *inner_nat_key,
+ flwd_active_ip_port_args_t *usable_active_ipport_args, flwd_raw_pkt_t *raw_pkt)
+{
+ flwd_nat_info_t *nat_info;
+
+ if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == inner_nat_key->addr_type)){
+ nat_info = flwd_create_new_nat_info_v4(tid, nat_type, inner_nat_key,
+ usable_active_ipport_args, raw_pkt);
+ }else{
+ nat_info = flwd_create_new_nat_info_v6(tid, nat_type, inner_nat_key,
+ usable_active_ipport_args, raw_pkt);
+ }
+
+ if(FLWD_IP_REGION_INLAND == usable_active_ipport_args->dip_region_type){
+ nat_info->act_ip_region = FLWD_IP_REGION_OUTLAND;
+ }else{
+ nat_info->act_ip_region = FLWD_IP_REGION_INLAND;
+ }
+
+ nat_info->nat_type = nat_type;
+
+#if FLWD_USE_LTSM_FOR_QUICK_CLOSE
+ nat_info->ltsm_stat_handle = ltsm_create_handle();
+#endif
+ return nat_info;
+}
+
+
+
+static flwd_nat_info_t * flwd_new_nat_session(flwd_device_handle_t *device_handle,
+ int tid, flwd_tuple5_t *nat_key, flwd_raw_pkt_t *raw_pkt)
+{
+ int ret;
+ flwd_nat_info_t *nat_info = NULL;
+ flwd_active_ip_port_args_t usable_active_ipport_args;
+ flwd_actual_ip_port_t actual_ipport_net_order;
+
+ memset(&usable_active_ipport_args, 0, sizeof(flwd_active_ip_port_args_t));
+
+ usable_active_ipport_args.dip_region_type = flwd_dstip_location(nat_key); /* �鿴Ŀ��IP��������λ�� */
+ usable_active_ipport_args.tid = tid;
+ usable_active_ipport_args.nat_key = nat_key;
+ usable_active_ipport_args.protocol = nat_key->protocol;
+
+ if(TOPO_ACC_LINK_USER == device_handle->io_para.topo_mode){
+ /* ACC_LINK�ӿ�, NATת����������, �϶���SNAT���װ�, �Ȳ���NAT���ò��� */
+ ret = flwd_access_snat_search_policy(tid, nat_key, &usable_active_ipport_args);
+ if(0 == ret){
+ /* �޲���, ��dynamic-ip-pool�������ѡһ��IP */
+ ret = flwd_access_snat_fetch_usable_ip_from_pool(flwd_thread_val[tid].flwd_ip_pool_dynamic_htable[nat_key->addr_type][(int)usable_active_ipport_args.dip_region_type ^ 1],
+ &flwd_thread_val[tid].flwd_ip_pool_dynamic_rwlock,
+ tid, nat_key, &usable_active_ipport_args);
+ if(ret < 0){
+ flwd_log(RLOG_LV_INFO, "tuple4 %s not hit any policy, but no according usable active ip in %s dynamic pool !\n",
+ flwd_tuple5_ntop(tid, nat_key),
+ flwd_ip_region_ntop((int)usable_active_ipport_args.dip_region_type ^ 1));
+
+ if(flwd_cfg_val.use_static_pool_ip_if_no_dynamic != 0){
+ ret = flwd_access_snat_fetch_usable_ip_from_pool(flwd_thread_val[tid].flwd_ip_pool_static_htable[nat_key->addr_type][(int)usable_active_ipport_args.dip_region_type ^ 1],
+ &flwd_thread_val[tid].flwd_ip_pool_static_rwlock,
+ tid, nat_key, &usable_active_ipport_args);
+ if(ret < 0){
+ flwd_log(RLOG_LV_FATAL, "tuple4 %s not hit any policy, but no according usable ip in all %s static and dynamic pool!\n",
+ flwd_tuple5_ntop(tid, nat_key),
+ flwd_ip_region_ntop((int)usable_active_ipport_args.dip_region_type ^ 1));
+ return NULL;
+ }
+ }else{
+ flwd_log(RLOG_LV_FATAL, "tuple4 %s not hit any policy, but no according usable active ip in %s dynamic pool, unfortunately 'use_static_pool_ip_if_no_dynamic' is disable!\n",
+ flwd_tuple5_ntop(tid, nat_key),
+ flwd_ip_region_ntop((int)usable_active_ipport_args.dip_region_type ^ 1));
+ return NULL;
+ }
+ }
+ }else if(-1 == ret){
+ if(flwd_cfg_val.use_dynamic_pool_ip_if_no_static != 0){
+ ret = flwd_access_snat_fetch_usable_ip_from_pool(flwd_thread_val[tid].flwd_ip_pool_static_htable[nat_key->addr_type][(int)usable_active_ipport_args.dip_region_type ^ 1],
+ &flwd_thread_val[tid].flwd_ip_pool_static_rwlock,
+ tid, nat_key, &usable_active_ipport_args);
+ if(ret < 0){
+ flwd_log(RLOG_LV_FATAL, "tuple4 %s hit policy, but no according usable ip in all %s static and dynamic pool!\n",
+ flwd_tuple5_ntop(tid, nat_key),
+ flwd_ip_region_ntop((int)usable_active_ipport_args.dip_region_type ^ 1));
+ return NULL;
+ }
+ }else{
+ flwd_log(RLOG_LV_FATAL, "tuple4 %s hit policy, but no according usable ip in %s static pool, unfortunately 'use_dynamic_pool_ip_if_no_static' is disable!\n",
+ flwd_tuple5_ntop(tid, nat_key),
+ flwd_ip_region_ntop((int)usable_active_ipport_args.dip_region_type ^ 1));
+ return NULL;
+ }
+ }
+
+ nat_info = flwd_create_new_nat_info(tid, FLWD_NAT_TYPE_SNAT, nat_key,
+ &usable_active_ipport_args, raw_pkt);
+
+ flwd_log(RLOG_LV_DEBUG, "---before signature, tuple4:%s",
+ flwd_tuple5_ntop(tid, &nat_info->outer_nat_tuple5));
+ flwd_acc_user_generate_pkt_signature(tid, nat_info, raw_pkt);
+ flwd_log(RLOG_LV_DEBUG, "---after signature, tuple4:%s",
+ flwd_tuple5_ntop(tid, &nat_info->outer_nat_tuple5));
+
+ }else if(TOPO_ACC_LINK_FWD == device_handle->io_para.topo_mode){
+ /* FWD���������װ�, ˵����DNAT��һ����, ���ݸ��ؾ�����Բ���������ʵ������IP�Ͷ˿� */
+#if FLWD_SUPPORT_DNAT
+ flwd_search_access_dnat_lb_policy(tid, nat_key, &actual_ipport_net_order);
+
+ nat_info = flwd_create_new_nat_info(tid, FLWD_NAT_TYPE_DNAT, nat_key,
+ &usable_active_ipport_args, raw_pkt);
+#endif
+ }
+
+ if(NULL == nat_info){
+#if FLWD_SUPPORT_DNAT
+ assert(0);
+#endif
+ return NULL;
+ }
+
+ if(flwd_new_nat_session_sotre(tid, nat_info) < 0){
+ return NULL;
+ }
+
+ char inner_tuple5_str[256];
+ char outer_tuple5_str[256];
+
+ flwd_log(10, "ACC: create new nat session, inner_tuple4:%s, outer_tuple4:%s\n",
+ flwd_tuple5_ntop_r(&nat_info->inner_nat_tuple5, inner_tuple5_str, 256),
+ flwd_tuple5_ntop_r(&nat_info->outer_nat_tuple5, outer_tuple5_str, 256));
+
+ return nat_info;
+}
+
+/*
+ access����user�հ�, ���nat��������, Ҫ��֤�Ϸ����װ�,
+ ������TCP->SYN, ������UDP��.
+
+ return value:
+ 0 : valid;
+ -1: invalid;
+*/
+static int flwd_acc_user_first_pkt_verify(const char *raw_eth_data)
+{
+ const flwd_eth_hdr_t *flwd_ethhdr = (flwd_eth_hdr_t *)raw_eth_data;
+ const flwd_ipv4_hdr_t *flwd_ip4hdr;
+ const flwd_ipv6_hdr_t *flwd_ip6hdr;
+ unsigned short eth_type = ntohs(flwd_ethhdr->h_proto);
+ const flwd_tcp_hdr_t *flwd_tcphdr;
+ int ret = 0;
+
+ if(ETH_P_IP == eth_type){
+ flwd_ip4hdr = (flwd_ipv4_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t));
+ if(IPPROTO_TCP == flwd_ip4hdr->ip_p){
+ flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_ip4hdr + flwd_ip4hdr->ip_hl * 4);
+ if(TH_SYN == flwd_tcphdr->th_flags){
+ ret = 0;
+ }else{
+ ret = -1;
+ }
+ }else if(IPPROTO_UDP == flwd_ip4hdr->ip_p){
+ ret = 0;
+ }
+ }else if(ETH_P_IPV6 == eth_type){
+ flwd_ip6hdr = (flwd_ipv6_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t));
+ if(IPPROTO_TCP == flwd_ip6hdr->ip6_nxt_hdr){
+ flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_ip6hdr + sizeof(flwd_ipv6_hdr_t));
+ if(TH_SYN == flwd_tcphdr->th_flags){
+ ret = 0;
+ }else{
+ ret = -1;
+ }
+ }else if(IPPROTO_UDP == flwd_ip4hdr->ip_p){
+ ret = 0;
+ }
+ }else{
+ assert(0);
+ }
+
+ return ret;
+}
+
+/*
+ access���ش�fwd�����հ�, ���nat��������, Ҫ��֤�Ϸ����װ�,
+ ������IP���ò���DNAT�е�ip,port;
+ ͬʱ��������TCP->SYN, ������UDP��.
+
+ �����SNAT, �϶�Ӧ�����ҵ�nat����֮ǰ�洢��Ԫ��.
+
+ return value:
+ 0 : valid;
+ -1: invalid;
+*/
+static int flwd_acc_fwd_first_pkt_verify(char *inner_mac_hdr)
+{
+ const flwd_eth_hdr_t *flwd_ethhdr = (flwd_eth_hdr_t *)inner_mac_hdr;
+ const flwd_ipv4_hdr_t *flwd_ip4hdr;
+ const flwd_ipv6_hdr_t *flwd_ip6hdr;
+ unsigned short eth_type = ntohs(flwd_ethhdr->h_proto);
+ const flwd_tcp_hdr_t *flwd_tcphdr;
+ int ret = 0;
+
+ if(ETH_P_IP == eth_type){
+ flwd_ip4hdr = (flwd_ipv4_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t));
+ if(IPPROTO_TCP == flwd_ip4hdr->ip_p){
+ flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_ip4hdr + flwd_ip4hdr->ip_hl * 4);
+ if(TH_SYN == flwd_tcphdr->th_flags){ /* ����DNAT��˵ */
+ ret = 0;
+ }if((TH_SYN|TH_ACK) == flwd_tcphdr->th_flags){ /* ����SNAT��˵ */
+ ret = 0;
+ }else{
+ ret = -1;
+ }
+ }else if(IPPROTO_UDP == flwd_ip4hdr->ip_p){
+ ret = 0;
+ }
+ }else if(ETH_P_IPV6 == eth_type){
+ flwd_ip6hdr = (flwd_ipv6_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t));
+ if(IPPROTO_TCP == flwd_ip6hdr->ip6_nxt_hdr){ /* TODO, IPv6���п��ܰ�������ͷ��, ��ʵ��Ӧ����ôֱ��ȡnext_hdr */
+ flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_ip6hdr + sizeof(flwd_ipv6_hdr_t));
+ if(TH_SYN == flwd_tcphdr->th_flags){ /* ����DNAT��˵ */
+ ret = 0;
+ }if((TH_SYN|TH_ACK) == flwd_tcphdr->th_flags){ /* ����SNAT��˵ */
+ ret = 0;
+ }else{
+ ret = -1;
+ }
+ }else if(IPPROTO_UDP == flwd_ip4hdr->ip_p){
+ ret = 0;
+ }
+ }else{
+ assert(0);
+ }
+
+ return ret;
+}
+
+/* �ͻ��˽��뷽��IP��, ���߰�ȥ������(��L2TP, PPTP������װ)����ʵ�ͻ����ڲ����ݰ���ں��� */
+int flwd_access_kernal_pkt_input(flwd_device_handle_t *device_handle,
+ int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ void *ip_strategy;
+ flwd_nat_info_t *nat_info;
+ char nat_key_buf[sizeof(flwd_tuple4v6_t)]; /* v4, v6����, ʹ��v6�ռ����� */
+ flwd_tuple5_t nat_key;
+ unsigned char dir_reverse;
+ int ret;
+ int ltsm_stat;
+ unsigned int out_opt = 0;
+
+ ret = flwd_build_tuple4_key(tid, &nat_key, raw_pkt);
+ if(ret < 0){
+ return -1;
+ }
+
+ nat_info = (flwd_nat_info_t *)MESA_htable_search(flwd_thread_val[tid].nat_info_table,
+ (const uchar *)&nat_key, sizeof(flwd_tuple5_t));
+ if(NULL == nat_info){
+ if((TOPO_ACC_LINK_USER == device_handle->io_para.topo_mode)
+ && (flwd_acc_user_first_pkt_verify(raw_pkt->outer_pkt_data) < 0)){
+ return -1;
+ }else if((TOPO_ACC_LINK_FWD == device_handle->io_para.topo_mode)
+ && (flwd_acc_fwd_first_pkt_verify(raw_pkt->inner_pkt_data) < 0)){
+ return -1;
+ }
+
+ nat_info = flwd_new_nat_session(device_handle, tid, &nat_key, raw_pkt);
+ if(NULL == nat_info){
+ if(TOPO_ACC_LINK_FWD == device_handle->io_para.topo_mode){
+ flwd_log(30, "recv pkt from gdev, but not found nat_info:%s!",
+ flwd_tuple5_ntop(tid, &nat_key));
+ }
+ return -1;
+ }
+ out_opt |= FLWD_OUTOPT_FIRST_PKT;
+ }
+
+ ltsm_stat = flwd_do_nat(device_handle, nat_info, raw_pkt);
+
+ flwd_access_output(device_handle, tid, nat_info, raw_pkt, out_opt);
+
+#if FLWD_USE_LTSM_FOR_QUICK_CLOSE
+ if(FTSM_CLOSED == ltsm_stat){
+ flwd_log(10, "tuple4 %s state is CLOSED, quick destroy nat_info!\n",
+ flwd_tuple5_ntop(tid, &nat_key));
+ MESA_htable_del(flwd_thread_val[tid].nat_info_table,
+ (const uchar *)&nat_key, sizeof(flwd_tuple5_t), NULL);
+ }
+#endif
+
+ return 0;
+}
+
+static void *flwd_access_nat_table_create(void)
+{
+ int opt_int;
+ MESA_htable_handle htable;
+
+ htable = MESA_htable_born();
+ assert(htable != NULL);
+
+ opt_int = 0; /* ÿ���̶߳���, ����ģʽ */
+ MESA_htable_set_opt(htable, MHO_THREAD_SAFE, &opt_int, sizeof(int));
+
+ opt_int = 1024 * 256;
+ MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, &opt_int, sizeof(int));
+
+ MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, &flwd_cfg_val.nat_htable_max_num, sizeof(int));
+
+ /* TODO, Ŀǰ���ó�ʱ��̭, ����TCPӦ��������״̬��, TCP������������̭, �����ͷ��ڴ� */
+ MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, &flwd_cfg_val.nat_htable_timeout, sizeof(int));
+
+ opt_int = HASH_ELIMINATE_ALGO_LRU;
+ MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, &opt_int, sizeof(int));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_KEY_COMPARE, (void *)&flwd_nat_htable_key_cmp, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_KEY_TO_INDEX, (void *)&flwd_nat_htable_key2index, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_COMPLEX_KEY_DUP, (void *)flwd_nat_htable_key_dup, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_COMPLEX_KEY_FREE, (void *)flwd_nat_htable_key_free, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, (void *)&flwd_access_nat_htable_data_free, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_DATA_EXPIRE_NOTIFY, (void *)&flwd_access_nat_htable_data_expire_notify, sizeof(void *));
+
+ opt_int = 1;
+ MESA_htable_set_opt(htable, MHO_AUTO_UPDATE_TIME, &opt_int, sizeof(int));
+
+ opt_int = 0;
+ MESA_htable_set_opt(htable, MHO_SCREEN_PRINT_CTRL, &opt_int, sizeof(int));
+
+ opt_int = 100;
+ MESA_htable_set_opt(htable, MHO_HASH_LIST_COLLIDE_THRESHOLD, &opt_int, sizeof(int));
+
+ char *err_log = (char *)"./flwd_hash_collide.log";
+ MESA_htable_set_opt(htable, MHO_HASH_LOG_FILE, (void *)err_log, strlen(err_log));
+
+ int ret = MESA_htable_mature(htable);
+ assert(ret >= 0);
+
+ return htable;
+}
+
+
+/*
+ �������ش�ת�����ط����հ�, ����vxlan��.
+*/
+static int flwd_acc_fwd_pkt_input(flwd_device_handle_t *rcv_device_handle,
+ int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ int ret;
+
+ raw_pkt->inner_ip_layer_hdr = (const char *)raw_pkt->outer_pkt_data + FLWD_VXLAN_OUTER_PACKET_LEN + sizeof(flwd_eth_hdr_t); /* �����������vxlanͷ�����ڲ�ethernetͷ�� */
+ raw_pkt->inner_pkt_data = (char *)raw_pkt->outer_pkt_data + FLWD_VXLAN_OUTER_PACKET_LEN; /* ָ���ڲ�ethernet��ʼ��ַ */
+ raw_pkt->inner_pkt_len = raw_pkt->outer_pkt_len - FLWD_VXLAN_OUTER_PACKET_LEN;
+ ret = flwd_access_kernal_pkt_input(rcv_device_handle, tid, raw_pkt);
+
+ return ret;
+}
+
+int flwd_acc_pkt_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ int ret;
+
+ flwd_thread_val[tid].pkt_stat.eth_pkt_num++;
+ flwd_thread_val[tid].pkt_stat.eth_pkt_byte += raw_pkt->outer_pkt_len;
+
+ if(TOPO_ACC_LINK_FWD == device_handle->io_para.topo_mode){
+ ret = flwd_rubbish_pkt_identify(device_handle, raw_pkt, 1);
+ }else{
+ ret = flwd_rubbish_pkt_identify(device_handle, raw_pkt, 0);
+ }
+ if(ret != 0){
+ return 0;
+ }
+
+ ret = flwd_protocol_stack_process(device_handle, tid, raw_pkt);
+ if(ret != 0){
+ return 0;
+ }
+
+ switch((int)device_handle->io_para.topo_mode){
+ case TOPO_ACC_LINK_USER:
+ flwd_log(10, "ACC: recv pkt from user client, tuple4:%s\n",
+ flwd_debug_print_tuple4_detail((char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t), tid));
+ flwd_acc_user_pkt_input(device_handle, tid, raw_pkt);
+ break;
+
+ case TOPO_ACC_LINK_FWD:
+ {
+ char inner_tuple4[128];
+ char outer_tuple4[128];
+ flwd_log(10, "ACC: recv pkt from forward gateway, inner_tuple4:%s, outer_tuple4:%s\n",
+ flwd_debug_print_tuple4_detail_r((char *)raw_pkt->outer_pkt_data + FLWD_VXLAN_OUTER_PACKET_LEN + sizeof(flwd_eth_hdr_t), inner_tuple4, 128),
+ flwd_debug_print_tuple4_detail_r((char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t), outer_tuple4, 128));
+
+ flwd_acc_fwd_pkt_input(device_handle, tid, raw_pkt);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+void *flwd_packet_io_work_thread(void *arg)
+{
+ int ret1, ret2, ret3;
+ int tseq = *((int *)arg);
+ flwd_raw_pkt_t raw_pkt;
+ unsigned long long last_idle_call_in_ms = 0;
+ flwd_device_handle_t *dev_handle;
+ int tot_work_times = 0; /* �ܽ��հ�, idle���� */
+ int success_work_times_in_recent_100 = 0; /* ���100�γɹ��Ĵ��� */
+
+ while(1){
+ dev_handle = &flwd_global_val.global_io_handle[TOPO_ACC_LINK_USER];
+ ret1 = dev_handle->low_level_pkt_recv(dev_handle, tseq, &raw_pkt.low_level_mbuff);
+ if(ret1 >= 0){
+ raw_pkt.outer_pkt_data = dev_handle->low_level_mbuff_mtod(raw_pkt.low_level_mbuff);
+ raw_pkt.outer_pkt_len = dev_handle->low_level_mbuff_get_pkt_len(raw_pkt.low_level_mbuff);
+ flwd_pre_process_pkt_input(dev_handle, &raw_pkt);
+ flwd_acc_pkt_input(dev_handle, tseq, &raw_pkt);
+ dev_handle->low_level_pkt_free(dev_handle, tseq, raw_pkt.low_level_mbuff);
+ }
+
+ dev_handle = &flwd_global_val.global_io_handle[TOPO_ACC_LINK_FWD];
+ ret2 = dev_handle->low_level_pkt_recv(dev_handle, tseq, &raw_pkt.low_level_mbuff);
+ if(ret2 >= 0){
+ raw_pkt.outer_pkt_data = dev_handle->low_level_mbuff_mtod(raw_pkt.low_level_mbuff);
+ raw_pkt.outer_pkt_len = dev_handle->low_level_mbuff_get_pkt_len(raw_pkt.low_level_mbuff);
+ flwd_pre_process_pkt_input(dev_handle, &raw_pkt);
+ flwd_acc_pkt_input(dev_handle, tseq, &raw_pkt);
+ dev_handle->low_level_pkt_free(dev_handle, tseq, raw_pkt.low_level_mbuff);
+ }
+
+ tot_work_times++;
+
+ if((ret1 < 0) && (ret2 < 0)){
+ ret3 = flwd_idle_call(tseq);
+ if(0 == ret3){
+ /* ����������������, idle_call()Ҳ���¿���, ����һ�� */
+ flwd_adapt_sleep(success_work_times_in_recent_100);
+ }else{
+ success_work_times_in_recent_100++;
+ }
+ }else{
+ success_work_times_in_recent_100++;
+ }
+
+ if(tot_work_times >= 100){
+ /////printf("%d/100\n", success_work_times_in_recent_100);
+ tot_work_times = 0;
+ success_work_times_in_recent_100 = 0;
+ }
+ }
+
+ return NULL;
+}
+
+/* �������س�ʼ������� */
+int flwd_gateway_init(void)
+{
+ int i, ret;
+ char str_tmp[256];
+
+#if FLWD_NO_ACTIVE_IP_DISCOVER
+ printf("\033[1;31;40m[Warning] TEST NO IP DISCOVER is enable!\033[0m\n" );
+ sleep(2);
+#endif
+
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "nat_htable_max_num", &flwd_cfg_val.nat_htable_max_num, 50000);
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "nat_htable_timeout", &flwd_cfg_val.nat_htable_timeout, 30);
+
+ for(i = 0; i < flwd_cfg_val.tot_thread_count; i++){
+ flwd_thread_val[i].nat_info_table = flwd_access_nat_table_create();
+ }
+
+
+ /* TODO, PPTP, L2TP server ��ʼ�� */
+
+ /* TODO, IP��ַ��ȫ��, ip-hot-pool �ṹ��ʼ�� */
+
+ /* IP���ò��Խṹ��ʼ��, HASH��, ����SNAT, keyΪdip+dport, ����DNAT, keyΪRIP+RPORT */
+
+ ret = flwd_packet_io_init(TOPO_ACC_LINK_USER, TOPO_ACC_LINK_FWD);
+ if(ret < 0){
+ return -1;
+ }
+
+ ret = flwd_access_active_ip_init();
+ if(ret < 0){
+ return -1;
+ }
+
+ ret = flwd_network_conn_init();
+ if(ret < 0){
+ return -1;
+ }
+
+ /* NOTE: maat��÷���������, ��Ϊ��callback, ��ʼ����ر���������, ����������ݽṹ��û��ʼ�����, ����flwd_access_active_ip_init(), callback�����! */
+ ret = flwd_access_maat_init();
+ if(ret < 0){
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/access/flwd_access_active_ip_manage.c b/src/access/flwd_access_active_ip_manage.c
new file mode 100644
index 0000000..8b3e876
--- /dev/null
+++ b/src/access/flwd_access_active_ip_manage.c
@@ -0,0 +1,616 @@
+/*
+ ��ԾIP��ַ����ģ��,
+ ����IP������ϵͳ��IP, ����MAAT-IP�ص���,
+*/
+#include "flowood.h"
+#include "flowood_fun.h"
+#include "flwd_net.h"
+#include "MESA_handle_logger.h"
+#include "MESA_htable.h"
+#include <arpa/inet.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+#include <assert.h>
+
+
+/*
+ TODO:
+ ȫ�����н������ط���Ψһ��id, ����Ȼ��1��ʼ,
+ ��������N����ÿ����������ʹ�õ�Դ�˿ڷ�Χ, ������1ʹ��10001-20000, ����2ʹ��20001-30000�ȵ�,
+ IP��ȫ�ֹ���, ��ͬ��������֮��Ķ˿ڰ���Χ����, ��֤���֮�以����ͻ!
+
+ ÿ�����������ڲ��ٸ����߳�����, ���������ö˿ڷֳ�THREAD_NUM��,
+ ������1���߳�1ʹ��10001-12000, ����1���߳�2ʹ��12001-14000, �ȵ�.
+*/
+
+
+MESA_ATOMIC_T flwd_temp_active_ip_op_flag[FLWD_MAX_THREAD_NUM];
+MESA_lqueue_head flwd_temp_active_ip_to_deal[FLWD_MAX_THREAD_NUM]; /* �ṹ: flwd_temp_to_deal_act_ip_t */
+
+
+typedef struct{
+ flwd_ip_t active_ip_net_order;
+ char is_valid; /* 1:usabel, add; 0:disable, del */
+}flwd_temp_to_deal_act_ip_t;
+
+static void flwd_act_ip_htable_data_free(void *data);
+
+
+static unsigned short flwd_act_ip_mask_to_num(unsigned short mask_to_num)
+{
+ int i;
+
+ for(i = 0; i < 16; i++){
+ if(0 != (mask_to_num & 1)){ /* һֱ����, ֱ�����λ��Ϊ0Ϊֹ */
+ break;
+ }else{
+ mask_to_num = mask_to_num >> 1;
+ }
+ }
+
+ return mask_to_num;
+}
+
+
+static unsigned short flwd_act_ip_get_acc_gateway_num(void)
+{
+ return flwd_act_ip_mask_to_num(FLWD_SPORT_ACC_ID_MASK);
+}
+
+unsigned short flwd_act_ip_get_usable_udp_sport_num(void)
+{
+ return flwd_act_ip_mask_to_num(FLWD_UDP_SPORT_ACTUAL_PORT_MASK);
+}
+
+unsigned short flwd_act_ip_get_usable_tcp_sport_num(void)
+{
+ return flwd_act_ip_mask_to_num(FLWD_TCP_SPORT_ACTUAL_PORT_MASK);
+}
+
+static int flwd_act_ip_get_tcp_usable_sport(int tid,
+ unsigned short *begin_port, unsigned short *usable_count)
+{
+ unsigned short this_gateway_begin_port;
+ unsigned short this_thread_usable_tot_count;
+ unsigned short this_gateway_usable_tot_count;
+
+ this_gateway_usable_tot_count = flwd_act_ip_get_usable_tcp_sport_num();
+
+ /* NOTE: current_access_gateway_idΪ�˷�������, ����Ȼ��1��ʼ, �˴���Ҫ��1, ���߳�id��0��ʼ, �����1 */
+
+ /* gateway_id���Ƶ����λ */
+ this_gateway_begin_port = (((unsigned short)flwd_cfg_val.current_access_gateway_id - 1) << (FLWD_SPORT_ACC_ID_SHIFT_NUM));
+
+ this_thread_usable_tot_count = this_gateway_usable_tot_count/flwd_cfg_val.tot_thread_count;
+
+ *usable_count = this_gateway_usable_tot_count/flwd_cfg_val.tot_thread_count;
+
+ *begin_port = this_gateway_begin_port | (*usable_count) * tid;
+
+ return 0;
+}
+
+
+static int flwd_act_ip_get_udp_usable_sport(int tid,
+ unsigned short *begin_port, unsigned short *usable_count)
+{
+ unsigned short this_gateway_begin_port;
+ unsigned short this_thread_usable_tot_count;
+ unsigned short this_gateway_usable_tot_count;
+
+ this_gateway_usable_tot_count = flwd_act_ip_get_usable_udp_sport_num();
+
+ /* NOTE: current_access_gateway_idΪ�˷�������, ����Ȼ��1��ʼ, �˴���Ҫ��1, ���߳�id��0��ʼ, �����1 */
+
+ /* gateway_id���Ƶ����λ */
+ this_gateway_begin_port = (((unsigned short)flwd_cfg_val.current_access_gateway_id - 1) << (FLWD_SPORT_ACC_ID_SHIFT_NUM));
+
+ this_thread_usable_tot_count = this_gateway_usable_tot_count/flwd_cfg_val.tot_thread_count;
+
+ *usable_count = this_gateway_usable_tot_count/flwd_cfg_val.tot_thread_count;
+
+ *begin_port = this_gateway_begin_port | (*usable_count) * tid;
+
+ return 0;
+}
+
+/*
+ NOTE:
+ ���ݻص����������Ļ�ԾIP, ��Ϊkey����htable,
+ ���ݵ�ǰ�������ص�id, ������������, ���߳�ID, ���ɿ��õĶ˿��б�.
+*/
+static flwd_active_ip_t *flwd_act_ip_create_new_node(int tid, const flwd_active_ip_t *act_ip_stack)
+{
+ flwd_active_ip_t *act_ip_heap;
+ unsigned short udp_begin_port, tcp_begin_port, tport;
+ unsigned short udp_usable_count, tcp_usable_count;
+ unsigned short i;
+ MESA_list_count_t *list_node;
+
+ act_ip_heap = (flwd_active_ip_t *)malloc(sizeof(flwd_active_ip_t));
+ memcpy(act_ip_heap, act_ip_stack, sizeof(flwd_active_ip_t));
+
+ MESA_list_init_head(&act_ip_heap->active_ip_list_node);
+ act_ip_heap->active_ip_list_node.quiddity = act_ip_heap; /* Ϊ�˽�Լ�ڴ�, ����ͷҲ�洢����, ��������dynamic���ͺͽ���һ��IP��static������˵, �������¹���һ���ڵ�, quiddityִ�������ṹ��ͷ�� */
+
+ /* TCP��UDP�Ķ˿ڷֿ��洢ʹ��, ������չһ����ԾIP��ʵ�ʸ��÷�Χ */
+ MESA_list_count_init_head(&act_ip_heap->usable_tcp_sport_list_head);
+ MESA_list_count_init_head(&act_ip_heap->usable_udp_sport_list_head);
+
+ flwd_act_ip_get_udp_usable_sport(tid, &udp_begin_port, &udp_usable_count);
+
+ for(i = 0; i < udp_usable_count; i++){
+ list_node = (MESA_list_count_t *)calloc(1, sizeof(MESA_list_count_t));
+ tport = udp_begin_port + i;
+ tport |= (flwd_cfg_val.current_access_gateway_id << FLWD_SPORT_ACC_ID_SHIFT_NUM);
+ tport = htons(tport); /* convert to net_order */
+ memcpy(&list_node->quiddity, &tport, sizeof(short)); /* ԭ���˴�������ָ��, ֱ�Ӹ����ڴ��ַ, �洢2���ֽڵĶ˿�ֵ, net_order */
+ MESA_list_count_add(&act_ip_heap->usable_udp_sport_list_head, list_node);
+ }
+
+ flwd_act_ip_get_tcp_usable_sport(tid, &tcp_begin_port, &tcp_usable_count);
+
+ for(i = 0; i < tcp_usable_count; i++){
+ list_node = (MESA_list_count_t *)calloc(1, sizeof(MESA_list_count_t));
+ tport = tcp_begin_port + i;
+ tport |= (flwd_cfg_val.current_access_gateway_id << FLWD_SPORT_ACC_ID_SHIFT_NUM);
+ tport = htons(tport); /* convert to net_order */
+
+ memcpy(&list_node->quiddity, &tport, sizeof(short)); /* ԭ���˴�������ָ��, ֱ�Ӹ����ڴ��ַ, �洢2���ֽڵĶ˿�ֵ, net_order */
+ MESA_list_count_add(&act_ip_heap->usable_tcp_sport_list_head, list_node);
+ }
+
+ return act_ip_heap;
+}
+
+#if FLWD_ASYNC_LOCK_FREE
+/* NOTE: �˺����ڰ������߳���������, ����ģʽ�����µĻ�Ծip */
+int flwd_act_ip_hash_proc(int tid, flwd_active_ip_t *act_ip_stack)
+{
+ MESA_htable_handle flwd_act_htable;
+ unsigned char *ip_key;
+ unsigned int ip_key_size;
+ flwd_active_ip_t *act_ip_heap;
+ int ret;
+ char ip_str[64];
+
+ if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == act_ip_stack->active_ip_net_order.addr_type)){
+ if(FLWD_IP_REGION_INLAND == act_ip_stack->ip_region_type){
+ flwd_act_htable = flwd_thread_val[tid].flwd_active_ipv4_pool_inland;
+ }else{
+ flwd_act_htable = flwd_thread_val[tid].flwd_active_ipv4_pool_outland;
+ }
+ ip_key = (unsigned char *)&act_ip_stack->active_ip_net_order.addr_ipv4;
+ ip_key_size = sizeof(int);
+ inet_ntop(AF_INET, &act_ip_stack->active_ip_net_order.addr_ipv4, ip_str, 64);
+ }else{
+ if(FLWD_IP_REGION_INLAND == act_ip_stack->ip_region_type){
+ flwd_act_htable = flwd_thread_val[tid].flwd_active_ipv6_pool_inland;
+ }else{
+ flwd_act_htable = flwd_thread_val[tid].flwd_active_ipv6_pool_outland;
+ }
+ ip_key = (unsigned char *)&act_ip_stack->active_ip_net_order.addr_ipv6;
+ ip_key_size = sizeof(struct in6_addr);
+ inet_ntop(AF_INET6, &act_ip_stack->active_ip_net_order.addr_ipv6, ip_str, 64);
+ }
+
+ if(act_ip_stack->is_valid){
+ if(MESA_htable_search(flwd_act_htable, ip_key, ip_key_size) == NULL){
+ act_ip_heap = flwd_act_ip_create_new_node(tid, act_ip_stack);
+ ret = MESA_htable_add(flwd_act_htable, ip_key, ip_key_size, act_ip_heap);
+ if(ret < 0){
+ flwd_act_ip_htable_data_free(act_ip_heap);
+ flwd_log(30, "add new active ip to htable fail, ret=%d\n", ret);
+ }else{
+ flwd_log(10, "add new active ip:%s\n", ip_str);
+ }
+ }else{
+ ; /* already exist, do nothing. */
+ }
+ }else{
+ /* */
+ MESA_htable_del(flwd_act_htable, ip_key, ip_key_size, NULL);
+ flwd_log(10, "del old active ip:%s\n", ip_str);
+ }
+
+ return 0;
+}
+#endif
+
+
+static void flwd_act_ip_dynamic_update(const flwd_active_ip_t *stack_act_ip)
+{
+ int i, ret;
+ flwd_active_ip_t *heap_act_ip;
+ unsigned int key_size;
+ unsigned char *key;
+ char ip_str[64];
+
+ if(FLWD_IP_ADDR_TYPE_V4 == stack_act_ip->active_ip_net_order.addr_type){
+ key = (unsigned char *)&stack_act_ip->active_ip_net_order.addr_ipv4;
+ key_size = sizeof(int);
+ }else{
+ key = (unsigned char *)&stack_act_ip->active_ip_net_order.addr_ipv6;
+ key_size = sizeof(struct in6_addr);
+ }
+
+ for(i = 0; i < flwd_cfg_val.tot_thread_count; i++){
+ pthread_rwlock_wrlock(&flwd_thread_val[i].flwd_ip_pool_dynamic_rwlock);
+
+ if(0 == stack_act_ip->is_valid){
+ MESA_htable_del(flwd_thread_val[i].flwd_ip_pool_dynamic_htable[stack_act_ip->active_ip_net_order.addr_type][stack_act_ip->ip_region_type],
+ key, key_size, NULL);
+ }else{
+ /* ���������, ����һ��, htable���Ƿ��Ѿ����� */
+ heap_act_ip = (flwd_active_ip_t *)MESA_htable_search(flwd_thread_val[i].flwd_ip_pool_dynamic_htable[stack_act_ip->active_ip_net_order.addr_type][stack_act_ip->ip_region_type],
+ key, key_size);
+ if(heap_act_ip != NULL){
+ /* ��ԾIP�ظ�, do nonthing !! */
+ pthread_rwlock_unlock(&flwd_thread_val[i].flwd_ip_pool_dynamic_rwlock);
+ return;
+ }
+
+ heap_act_ip = flwd_act_ip_create_new_node(i, stack_act_ip);
+ ret = MESA_htable_add(flwd_thread_val[i].flwd_ip_pool_dynamic_htable[stack_act_ip->active_ip_net_order.addr_type][stack_act_ip->ip_region_type],
+ key, key_size, heap_act_ip);
+ assert(ret >= 0);
+ flwd_log(10, "add dynamic ip pool addr:'%s'\n ", flwd_ipt_ntop_r(&stack_act_ip->active_ip_net_order, ip_str, 64));
+ }
+
+ pthread_rwlock_unlock(&flwd_thread_val[i].flwd_ip_pool_dynamic_rwlock);
+ }
+
+ return;
+}
+
+
+/* �ж�IP�Ƿ�����е��ظ�(�˹�����, ���������ظ�IP), ������ʱҲ���ܸ���һ����IP�Ͷ˿�, ������� */
+
+static int flwd_static_ip_pool_is_dup(const flwd_active_ip_t *act_ip_head,
+ const flwd_active_ip_t *stack_act_ip)
+{
+ const MESA_list_t *in_list_node = &act_ip_head->active_ip_list_node;
+ const flwd_active_ip_t *in_list_ipt;
+
+ do{
+ in_list_ipt = (flwd_active_ip_t *)in_list_node->quiddity;
+ if(flwd_ipt_equal(&in_list_ipt->active_ip_net_order, &stack_act_ip->active_ip_net_order) == 1){
+ return 1;
+ }
+ in_list_node = in_list_node->nextele;
+ }while(in_list_node != &act_ip_head->active_ip_list_node); /* ˫��ѭ������, ��ֹ��ѭ�� */
+
+ return 0;
+}
+
+
+/* ��̬IP����group_idΪkey, IP_listΪdata */
+static void flwd_act_ip_static_update(const flwd_active_ip_t *stack_act_ip)
+{
+ int i, ret;
+ flwd_active_ip_t *act_ip_head;/* htable�е�ip�ڵ� */
+ flwd_active_ip_t *heap_act_ip; /* ����������ip */
+ char ip_str[64];
+ void *ip_static_htable;
+
+ /* NOTE: ���Ӻ�ɾ��IPʱʹ��group_id����ip_list, Ȼ���ٱ���; �����ö˿ڻ���ʱ, ֻ��IP�Ͷ˿�, û��Group_id�ĸ���,
+ ��flwd_ip_pool_static_htable��, ʹ��������ͬ��key, ����ͬһ��data, ��ip_list.
+
+ update_cbʹ��group_id����ip_list;
+ sport_recycleʹ��ip��ַ����ip_list;
+
+ Ϊ�˷�ֹ��һgroup_id��ipv4��ַ��ͻ, ��groupתΪ�ַ���ģʽ, ǰ�����GPIDǰ׺, ������֤key�ij��ȶ���һ��, �϶�Ҳ�����ͻ.
+ */
+ unsigned char static_ip_group_key[64];
+ int static_ip_group_key_len = 64;
+ flwd_policy_group_id_key_gen(stack_act_ip->policy_group_id, static_ip_group_key, &static_ip_group_key_len);
+
+ for(i = 0; i < flwd_cfg_val.tot_thread_count; i++){
+ /* NOTE: �˺�������maat�ص��߳�������, �����������̵߳����ݽṹ, ��Ҫ����! */
+ pthread_rwlock_wrlock(&flwd_thread_val[i].flwd_ip_pool_static_rwlock);
+
+ ip_static_htable = flwd_thread_val[i].flwd_ip_pool_static_htable[stack_act_ip->active_ip_net_order.addr_type][stack_act_ip->ip_region_type];
+
+ if(0 == stack_act_ip->is_valid){
+ flwd_ip_pool_del(FLWD_ACT_IP_STATIC,
+ ip_static_htable,
+ stack_act_ip->policy_group_id,
+ flwd_act_ip_htable_data_free,
+ stack_act_ip);
+ }else{
+ /* ���������, ����һ��htable���Ƿ��Ѿ����� */
+ act_ip_head = (flwd_active_ip_t *)flwd_ip_pool_search(FLWD_ACT_IP_STATIC,
+ ip_static_htable,
+ (unsigned char *)static_ip_group_key,
+ static_ip_group_key_len);
+ if(act_ip_head != NULL){
+ /* group-list�Ѵ���, �ж�IP�Ƿ�����е��ظ�(�˹�����, ���������ظ�IP), ������ʱҲ���ܸ���һ����IP�Ͷ˿�, ������� */
+ if(flwd_static_ip_pool_is_dup(act_ip_head, stack_act_ip) == 0){
+ heap_act_ip = flwd_act_ip_create_new_node(i, stack_act_ip);
+
+ MESA_list_add(&act_ip_head->active_ip_list_node, &heap_act_ip->active_ip_list_node);
+
+ /* ��ipΪkey, �ٲ���һ��hash��, ���ڶ˿ڻ���ʱ, û��group_id, Ҳ�ܿ�ip�ҵ���Ӧ��ip_list */
+ ret = MESA_htable_add(ip_static_htable,
+ stack_act_ip->active_ip_net_order.addr_value,
+ stack_act_ip->active_ip_net_order.addr_len,
+ heap_act_ip);
+ assert(ret >= 0);
+ flwd_log(10, "add static ip pool addr:'%s'\n ",
+ flwd_ipt_ntop_r(&stack_act_ip->active_ip_net_order, ip_str, 64));
+ }else{
+ flwd_log(20, "static ip pool %s is duplicated!\n ",
+ flwd_ipt_ntop_r(&stack_act_ip->active_ip_net_order, ip_str, 64));
+ }
+ }else{
+ /* ��ǰpolicy��û��IP, ��һ��, Ҳ����������ͷ�ڵ�, ֱ����MESA_htable_add����, */
+ heap_act_ip = flwd_act_ip_create_new_node(i, stack_act_ip);
+ ret = MESA_htable_add(ip_static_htable,
+ (unsigned char *)static_ip_group_key,
+ static_ip_group_key_len,
+ heap_act_ip);
+ assert(ret >= 0);
+ /* ��ipΪkey, �ٲ���һ��hash��, ���ڶ˿ڻ���ʱ, û��group_id, Ҳ�ܿ�ip�ҵ���Ӧ��ip_list */
+ ret = MESA_htable_add(ip_static_htable,
+ stack_act_ip->active_ip_net_order.addr_value,
+ stack_act_ip->active_ip_net_order.addr_len,
+ heap_act_ip);
+ if(ret < 0){
+ /* ������IP�ظ���! �����Dz�ͬ�������������ͬ��IP��ַ! */
+ /* TODO, ���������ô��?? ͬһ��IP���ڲ�ͬ����, �ɲ�����?? */
+ //flwd_act_ip_htable_data_free(heap_act_ip);
+ flwd_log(30, "add static ip pool addr:'%s' error, ret=%d\n ",
+ flwd_ipt_ntop_r(&stack_act_ip->active_ip_net_order, ip_str, 64), ret);
+ }else{
+ flwd_log(10, "add static ip pool addr:'%s'\n ",
+ flwd_ipt_ntop_r(&stack_act_ip->active_ip_net_order, ip_str, 64));
+ }
+ }
+ }
+
+ pthread_rwlock_unlock(&flwd_thread_val[i].flwd_ip_pool_static_rwlock);
+ }
+
+ return;
+}
+
+/*
+ NOTE:
+ ��̬��ԾIP��IP��ַΪkey, dataΪflwd_active_ip_t, ֻ����һ���ڵ�, active_ip_list_nodeָ�붼�ǿ�;
+ ��̬IP��ַ�صĵ�ַ�Բ�����IDΪkey, dataΪflwd_active_ip_t������, ����������ͬpolicy_id��IP;
+*/
+void flwd_act_ip_update(const flwd_active_ip_t *stack_act_ip)
+{
+ if(FLWD_ACT_IP_DYNAMIC == stack_act_ip->ip_origin_type){
+ flwd_act_ip_dynamic_update(stack_act_ip);
+ }else{
+ flwd_act_ip_static_update(stack_act_ip);
+ }
+
+ return;
+}
+
+
+
+#if FLWD_NO_ACTIVE_IP_DISCOVER
+/* ģ���ԾIP����ϵͳ, ��һЩ������ģ�� */
+
+/*
+ ���ݿ����ʽ:
+ "id addr_type ipaddr port user_region(GDEV_IP) location is_valid op_time"
+ "1 4 11.22.33.44 0 100 0 1 2018-06-03 11:11:11"
+*/
+static void flwd_phony_act_ipv4_gen(int is_valid, unsigned ip_addr, unsigned int group_id, flwd_ip_region_type_t region_type, flwd_active_ip_type_t origin_type)
+{
+ int rand_num;
+ flwd_active_ip_t stack_act_ip;
+
+ rand_num = rand();
+
+ stack_act_ip.is_valid = is_valid;
+ stack_act_ip.policy_group_id = group_id;
+
+ stack_act_ip.ip_region_type = region_type; /* ����ip���� */
+
+ stack_act_ip.ip_origin_type = origin_type;
+
+ stack_act_ip.active_ip_net_order.addr_ipv4 = ip_addr;
+ stack_act_ip.active_ip_net_order.addr_type = FLWD_IP_ADDR_TYPE_V4;
+ stack_act_ip.active_ip_net_order.addr_len = sizeof(int);
+
+ stack_act_ip.gdev_args.gdev_ip_net_order = 0x01010101;
+
+ flwd_act_ip_update(&stack_act_ip);
+
+}
+
+static void *flwd_act_ip_phony_discoverer(void *arg)
+{
+ int i = 0;
+ time_t tstart;
+
+ tstart = time(NULL);
+
+ while(1){
+ for(i = 0; i < 100; i++){
+ flwd_phony_act_ipv4_gen(1, i, i, FLWD_IP_REGION_INLAND, FLWD_ACT_IP_DYNAMIC);
+ flwd_phony_act_ipv4_gen(1, i, i, FLWD_IP_REGION_OUTLAND, FLWD_ACT_IP_DYNAMIC);
+
+ flwd_phony_act_ipv4_gen(1, i, i, FLWD_IP_REGION_INLAND, FLWD_ACT_IP_STATIC);
+ flwd_phony_act_ipv4_gen(1, i, i, FLWD_IP_REGION_OUTLAND, FLWD_ACT_IP_STATIC);
+ }
+
+ usleep(10);
+#if 1
+ for(i = 0; i < 100; i++){
+ flwd_phony_act_ipv4_gen(0, i, i, FLWD_IP_REGION_INLAND, FLWD_ACT_IP_DYNAMIC);
+ flwd_phony_act_ipv4_gen(0, i, i, FLWD_IP_REGION_INLAND, FLWD_ACT_IP_STATIC);
+ flwd_phony_act_ipv4_gen(0, i, i, FLWD_IP_REGION_OUTLAND, FLWD_ACT_IP_DYNAMIC);
+ flwd_phony_act_ipv4_gen(0, i, i, FLWD_IP_REGION_OUTLAND, FLWD_ACT_IP_STATIC);
+ }
+#endif
+
+ if(tstart + 60 < time(NULL)){
+ sleep(5);
+ exit(1);
+ }
+ }
+
+ return NULL;
+}
+#endif
+
+static int flwd_act_ip_htable_key_cmp(const uchar * key1, uint size1, const uchar * key2, uint size2)
+{
+ if(size1 != size2){
+ return -1;
+ }
+
+ return memcmp(key1, key2, size1);
+}
+
+static uint flwd_act_ip_htable_key2index(const MESA_htable_handle table, const uchar * key, uint size)
+{
+ unsigned int hash = 131;
+ unsigned seed = 13131;
+ unsigned int i;
+
+ for(i = 0; i < size; i++){
+ hash = hash * seed + *key++;
+ }
+
+ return hash;
+}
+
+static void flwd_act_ip_htable_data_free(void *data)
+{
+ flwd_active_ip_t *act_ip = (flwd_active_ip_t *)data;
+ MESA_list_count_t *list_node, *next_node;
+ char ip_str[64];
+
+ while((0 == MESA_list_count_is_empty(&act_ip->usable_tcp_sport_list_head))){
+ list_node = act_ip->usable_tcp_sport_list_head.nextele;
+ MESA_list_count_del(&act_ip->usable_tcp_sport_list_head, list_node);
+ free(list_node);
+ }
+
+ while((0 == MESA_list_count_is_empty(&act_ip->usable_udp_sport_list_head))){
+ list_node = act_ip->usable_udp_sport_list_head.nextele;
+ MESA_list_count_del(&act_ip->usable_udp_sport_list_head, list_node);
+ free(list_node);
+ }
+
+ flwd_log(10, "del ip pool addr:'%s'\n ", flwd_ipt_ntop_r(&act_ip->active_ip_net_order, ip_str, 64));
+
+ memset(act_ip, 0xFE, sizeof(flwd_active_ip_t));
+
+ free(data);
+}
+
+static MESA_htable_handle flwd_act_ip_htable_create(void)
+{
+ int opt_int;
+ MESA_htable_handle htable;
+
+ htable = MESA_htable_born();
+ assert(htable != NULL);
+
+ opt_int = 0; /* ���ⲿ��rwlock��д��ʵ�ֶ��̰߳�ȫ, ��htable�ڲ��Ļ��������ܸ���һЩ */
+ MESA_htable_set_opt(htable, MHO_THREAD_SAFE, &opt_int, sizeof(int));
+
+ opt_int = 1024 * 32;
+ MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, &opt_int, sizeof(int));
+
+ opt_int = 100000;
+ MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, &opt_int, sizeof(int));
+
+ opt_int = 0; /* ��ԾIP�ص����г�ʱɾ������, ��redis�ص�ʵ��, ����htable������ʱ */
+ MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, &opt_int, sizeof(int));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_KEY_COMPARE, (void *)&flwd_act_ip_htable_key_cmp, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_KEY_TO_INDEX, (void *)&flwd_act_ip_htable_key2index, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, (void *)&flwd_act_ip_htable_data_free, sizeof(void *));
+
+ opt_int = 1;
+ MESA_htable_set_opt(htable, MHO_AUTO_UPDATE_TIME, &opt_int, sizeof(int));
+
+ opt_int = 0;
+ MESA_htable_set_opt(htable, MHO_SCREEN_PRINT_CTRL, &opt_int, sizeof(int));
+
+ /* searchʱ�ӵ��Ƕ���, ֻ����FIFOģʽ, LRUģʽ�ڲ���д���� */
+ opt_int = HASH_ELIMINATE_ALGO_FIFO;
+ MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, &opt_int, sizeof(int));
+
+ opt_int = 100;
+ MESA_htable_set_opt(htable, MHO_HASH_LIST_COLLIDE_THRESHOLD, &opt_int, sizeof(int));
+
+ char *err_log = (char *)"./flwd_hash_collide.log";
+ MESA_htable_set_opt(htable, MHO_HASH_LOG_FILE, (void *)err_log, strlen(err_log));
+
+ int ret = MESA_htable_mature(htable);
+ assert(ret >= 0);
+
+ return htable;
+}
+
+
+/*
+ TODO:
+ ����SNAT��˵, act_ip����IP������ϵͳ�ش���IP, ��������;
+ ����DNAT��˵, act_ip�ǽ��������������ip, ��Ϊֻ��һ��ip����65535���˿ڿ���, �������ļ��������������⶯̬ip��ʼ��ַ������:
+
+ [TOPO_ACC_LINK_USER]
+ gateway_slave_ip_range = 10.0.9.100
+ gateway_slave_ip_num = 10
+
+ ��˼�Ǵ�10.0.9.100��ʼ, ��10.0.9.109���ǽ�����������������ʵ�ڲ���������ip,
+ Ҫ������ЩIP��arp����, �ظ�Ӧ���.
+*/
+
+
+int flwd_access_active_ip_init(void)
+{
+ int i;
+ int v4_or_v6, in_or_out;
+
+ for(i = 0; i < flwd_cfg_val.tot_thread_count; i++){
+ flwd_temp_active_ip_to_deal[i] = MESA_lqueue_create(0, 1000); /* �첽������б�������, ��ԭ�ӱ������� */
+
+ MESA_ATOMIC_SET(flwd_temp_active_ip_op_flag[i], 0);
+#if 0
+ flwd_thread_val[i].flwd_active_ipv4_pool_inland = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_active_ipv4_pool_outland = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_active_ipv6_pool_inland = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_active_ipv6_pool_outland = flwd_act_ip_htable_create();
+
+ flwd_thread_val[i].flwd_static_ipv4_pool_inland = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_static_ipv4_pool_outland = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_static_ipv6_pool_inland = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_static_ipv6_pool_outland = flwd_act_ip_htable_create();
+#else
+ for(v4_or_v6 = 0; v4_or_v6 <= 1; v4_or_v6++){
+ for(in_or_out = 0; in_or_out <= 1; in_or_out++){
+ flwd_thread_val[i].flwd_ip_pool_dynamic_htable[v4_or_v6][in_or_out] = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_ip_pool_static_htable[v4_or_v6][in_or_out] = flwd_act_ip_htable_create();
+ }
+ }
+ pthread_rwlock_init(&flwd_thread_val[i].flwd_ip_pool_dynamic_rwlock, NULL);
+ pthread_rwlock_init(&flwd_thread_val[i].flwd_ip_pool_static_rwlock, NULL);
+#endif
+ }
+
+#if FLWD_NO_ACTIVE_IP_DISCOVER
+ pthread_t pid;
+
+ pthread_create(&pid, NULL, flwd_act_ip_phony_discoverer, NULL);
+#endif
+
+ return 0;
+}
+
diff --git a/src/access/flwd_access_idle_call.c b/src/access/flwd_access_idle_call.c
new file mode 100644
index 0000000..a842728
--- /dev/null
+++ b/src/access/flwd_access_idle_call.c
@@ -0,0 +1,66 @@
+/*
+ �����������ݰ�, CPU����ʱ, �ڰ������̵߳��������е��ô˽ӿ�,
+ ������htable��ʱ��̭,
+ ��ԾIP���ø���(ԭ�����޲��Ե�, �û�������һ������, ����в��Ե���; ��֮, ԭ�������в���, ��ɾ����),
+
+ ��˺����ӿ��ڰ������̵߳���������, ��ʵ�ְ������߳���������ʱ������, �������!!
+*/
+#include "flowood.h"
+#include "flowood_fun.h"
+#include "flwd_net.h"
+#include "MESA_handle_logger.h"
+#include "MESA_atomic.h"
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+#include <assert.h>
+
+extern MESA_ATOMIC_T flwd_temp_active_ip_op_flag[FLWD_MAX_THREAD_NUM];
+
+
+/* �ڰ������߳������Ĵ�����ԾIP�ĸ���, ����ģʽ */
+static int flwd_act_ip_update_in_process_thread_context(int tid)
+{
+#if FLWD_ASYNC_LOCK_FREE
+ int ret;
+ flwd_active_ip_t tmp_act_ip;
+ long buf_len;
+
+ if(0 == MESA_lqueue_get_count(flwd_temp_active_ip_to_deal[tid])){
+ /* û���µ����� */
+ return 0;
+ }
+
+ if(FLWD_ACT_IP_OP_OR_MASK_BY_CALLBACK & __sync_or_and_fetch(&flwd_temp_active_ip_op_flag[tid], FLWD_ACT_IP_OP_OR_MASK_BY_PROC)){
+ /* callback�̻߳��ڴ�����, �˴����ܵȴ�, ��ձ�־λ��, ֱ�ӷ��ص���һ�ε��� */
+ __sync_and_and_fetch(&flwd_temp_active_ip_op_flag[tid], FLWD_ACT_IP_OP_AND_MASK_BY_PROC);
+ return 0;
+ }
+
+ buf_len = sizeof(flwd_active_ip_t);
+ ret = MESA_lqueue_get_head(flwd_temp_active_ip_to_deal[tid], &tmp_act_ip, &buf_len);
+ assert(ret >= 0);
+
+ flwd_act_ip_hash_proc(tid, &tmp_act_ip);
+
+ /* �������, �����־λ */
+ __sync_and_and_fetch(&flwd_temp_active_ip_op_flag[tid], FLWD_ACT_IP_OP_AND_MASK_BY_PROC);
+
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+
+int flwd_idle_call(int tid)
+{
+ int ret;
+ ret = flwd_act_ip_update_in_process_thread_context(tid);
+
+ return ret;
+}
+
diff --git a/src/access/flwd_access_ip_layer.c b/src/access/flwd_access_ip_layer.c
new file mode 100644
index 0000000..1fcfb4a
--- /dev/null
+++ b/src/access/flwd_access_ip_layer.c
@@ -0,0 +1,6 @@
+#include "flowood.h"
+#include "flowood_fun.h"
+#include "flwd_net.h"
+
+
+
diff --git a/src/access/flwd_access_l2tp_layer.c b/src/access/flwd_access_l2tp_layer.c
new file mode 100644
index 0000000..43c76af
--- /dev/null
+++ b/src/access/flwd_access_l2tp_layer.c
@@ -0,0 +1,22 @@
+#include "flowood.h"
+#include "flowood_fun.h"
+#include "flwd_net.h"
+#include "MESA_handle_logger.h"
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+#include <assert.h>
+
+
+int flwd_access_l2tp_layer_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ /* TODO, ����l2tpЭ��ջ����, �ҵ�l2tp���, ������Ϻ�, ����access���Ĵ���ģ�� */
+
+ flwd_access_kernal_pkt_input(device_handle, tid, raw_pkt);
+
+ return 0;
+}
+
diff --git a/src/access/flwd_access_maat.c b/src/access/flwd_access_maat.c
new file mode 100644
index 0000000..be30508
--- /dev/null
+++ b/src/access/flwd_access_maat.c
@@ -0,0 +1,582 @@
+#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 <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+#include <assert.h>
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <ctype.h>
+
+
+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;
+}
+