From 86a43b4d325ddc850fa9dc4711670880f35b11e8 Mon Sep 17 00:00:00 2001 From: lijia Date: Wed, 24 Oct 2018 09:36:45 +0800 Subject: create new project. --- Makefile | 44 + bin/conf/flowood.conf | 62 + bin/conf/maat_tableinfo.conf | 16 + bin/conf/maat_test.json | 89 ++ .../IR_DYN_SIFT_IP_CB.local | 2 + .../IR_POLICY_COMPILE.local | 3 + .../maat_test.json_iris_tmp/IR_POLICY_GROUP.local | 3 + .../maat_test.json_iris_tmp/IR_POLICY_IP.local | 3 + .../IR_STATIC_IP_POOL_CB.local | 3 + .../index/full_config_index.0000000001 | 5 + bin/conf/network_access.cfg | 4 + bin/conf/network_connect.cfg | 6 + bin/conf/network_forward.cfg | 6 + bin/conf/network_gdev.cfg | 6 + bin/flowood_keepalive.py | 19 + bin/flwd_r2 | 3 + bin/flwd_r3 | 17 + bin/io_lib/flwd_io_pcap.so | Bin 0 -> 30411 bytes bin/io_lib/flwd_io_socket.so | Bin 0 -> 26649 bytes bin/memchk.sh | 2 + bin/rulescan_tmp/rulescan_iie.log | 0 deploy.txt | 13 + deploy/ethtool | 3 + deploy/ip_forward | 1 + deploy/iptable_drop_rst | 1 + deploy/l2tp/xl2tpd-1.3.8-8.fc29.x86_64.rpm | Bin 0 -> 91900 bytes deploy/pptpd/pptpd_install/auth-down | 7 + deploy/pptpd/pptpd_install/auth-up | 19 + deploy/pptpd/pptpd_install/chap-secrets | 58 + deploy/pptpd/pptpd_install/options.pptpd | 134 ++ .../pptpd_install/pptpd-1.4.0-2.el7.x86_64.rpm | Bin 0 -> 81428 bytes deploy/pptpd/pptpd_install/pptpd.conf | 106 ++ deploy/pptpd/pptpd_install/pptpd.install.sh | 16 + deploy/problem | 2 + deploy/user_pass | 8 + inc/flowood.h | 491 ++++++ inc/flowood_fun.h | 92 ++ inc/flwd_net.h | 389 +++++ inc/ltsm.h | 117 ++ lib/libltsm.a | Bin 0 -> 5968 bytes src/Makefile | 59 + src/access/Makefile | 26 + src/access/flowood_access.c | 1656 ++++++++++++++++++++ src/access/flwd_access_active_ip_manage.c | 616 ++++++++ src/access/flwd_access_idle_call.c | 66 + src/access/flwd_access_ip_layer.c | 6 + src/access/flwd_access_l2tp_layer.c | 22 + src/access/flwd_access_maat.c | 582 +++++++ src/common/Makefile | 42 + src/common/flwd_arp.c | 252 +++ src/common/flwd_common_hash.c | 98 ++ src/common/flwd_common_maat.c | 153 ++ src/common/flwd_common_stack.c | 449 ++++++ src/common/flwd_common_tool.c | 911 +++++++++++ src/common/flwd_compat_marsio_hash.c | 23 + src/common/flwd_network_connect.c | 363 +++++ src/common/flwd_sendpacket.c | 138 ++ src/common/flwd_status.c | 275 ++++ src/common/linux_jhash_algo.c | 267 ++++ src/flowood_main.c | 155 ++ src/forward/Makefile | 27 + src/forward/flowood_forward.c | 1044 ++++++++++++ src/forward/flwd_fwd_idle_call.c | 5 + src/forward/flwd_fwd_maat.c | 40 + src/packet_io/Makefile | 34 + src/packet_io/flwd_io_pcap.so | Bin 0 -> 30411 bytes src/packet_io/flwd_io_socket.so | Bin 0 -> 26649 bytes src/packet_io/flwd_packet_io.c | 193 +++ src/packet_io/flwd_packet_io_pcap.c | 428 +++++ src/packet_io/flwd_packet_io_socket.c | 376 +++++ src/packet_io/nf-queue.c | 213 +++ src/packet_io/nfq_test.c | 270 ++++ support/include/MESA_atomic_for_view.h | 38 + support/include/MESA_handle_logger_for_view.h | 68 + support/include/MESA_htable_for_view.h | 393 +++++ support/include/MESA_list_count_for_view.h | 31 + support/include/MESA_list_for_view.h | 34 + support/include/MESA_list_queue_for_view.h | 115 ++ support/include/MESA_prof_load_for_view.h | 179 +++ support/include/MESA_ring_queue_for_view.h | 107 ++ support/include/Maat_command_for_view.h | 154 ++ support/include/Maat_rule_for_view.h | 228 +++ support/include/field_stat2_for_view.h | 66 + ...4\213_\344\270\215\347\274\226\350\257\221.txt" | 0 support/ltsm/Makefile | 14 + support/ltsm/ltsm.c | 485 ++++++ support/ltsm/ltsm.h | 117 ++ support/ltsm/ltsm_with_hash.h | 81 + support/ltsm/test_ltsm.c | 59 + test/mutex_vs_rdlock.c | 138 ++ test/sport_usable.c | 45 + 91 files changed, 12891 insertions(+) create mode 100644 Makefile create mode 100644 bin/conf/flowood.conf create mode 100644 bin/conf/maat_tableinfo.conf create mode 100644 bin/conf/maat_test.json create mode 100644 bin/conf/maat_test.json_iris_tmp/IR_DYN_SIFT_IP_CB.local create mode 100644 bin/conf/maat_test.json_iris_tmp/IR_POLICY_COMPILE.local create mode 100644 bin/conf/maat_test.json_iris_tmp/IR_POLICY_GROUP.local create mode 100644 bin/conf/maat_test.json_iris_tmp/IR_POLICY_IP.local create mode 100644 bin/conf/maat_test.json_iris_tmp/IR_STATIC_IP_POOL_CB.local create mode 100644 bin/conf/maat_test.json_iris_tmp/index/full_config_index.0000000001 create mode 100644 bin/conf/network_access.cfg create mode 100644 bin/conf/network_connect.cfg create mode 100644 bin/conf/network_forward.cfg create mode 100644 bin/conf/network_gdev.cfg create mode 100644 bin/flowood_keepalive.py create mode 100644 bin/flwd_r2 create mode 100644 bin/flwd_r3 create mode 100644 bin/io_lib/flwd_io_pcap.so create mode 100644 bin/io_lib/flwd_io_socket.so create mode 100644 bin/memchk.sh create mode 100644 bin/rulescan_tmp/rulescan_iie.log create mode 100644 deploy.txt create mode 100644 deploy/ethtool create mode 100644 deploy/ip_forward create mode 100644 deploy/iptable_drop_rst create mode 100644 deploy/l2tp/xl2tpd-1.3.8-8.fc29.x86_64.rpm create mode 100644 deploy/pptpd/pptpd_install/auth-down create mode 100644 deploy/pptpd/pptpd_install/auth-up create mode 100644 deploy/pptpd/pptpd_install/chap-secrets create mode 100644 deploy/pptpd/pptpd_install/options.pptpd create mode 100644 deploy/pptpd/pptpd_install/pptpd-1.4.0-2.el7.x86_64.rpm create mode 100644 deploy/pptpd/pptpd_install/pptpd.conf create mode 100644 deploy/pptpd/pptpd_install/pptpd.install.sh create mode 100644 deploy/problem create mode 100644 deploy/user_pass create mode 100644 inc/flowood.h create mode 100644 inc/flowood_fun.h create mode 100644 inc/flwd_net.h create mode 100644 inc/ltsm.h create mode 100644 lib/libltsm.a create mode 100644 src/Makefile create mode 100644 src/access/Makefile create mode 100644 src/access/flowood_access.c create mode 100644 src/access/flwd_access_active_ip_manage.c create mode 100644 src/access/flwd_access_idle_call.c create mode 100644 src/access/flwd_access_ip_layer.c create mode 100644 src/access/flwd_access_l2tp_layer.c create mode 100644 src/access/flwd_access_maat.c create mode 100644 src/common/Makefile create mode 100644 src/common/flwd_arp.c create mode 100644 src/common/flwd_common_hash.c create mode 100644 src/common/flwd_common_maat.c create mode 100644 src/common/flwd_common_stack.c create mode 100644 src/common/flwd_common_tool.c create mode 100644 src/common/flwd_compat_marsio_hash.c create mode 100644 src/common/flwd_network_connect.c create mode 100644 src/common/flwd_sendpacket.c create mode 100644 src/common/flwd_status.c create mode 100644 src/common/linux_jhash_algo.c create mode 100644 src/flowood_main.c create mode 100644 src/forward/Makefile create mode 100644 src/forward/flowood_forward.c create mode 100644 src/forward/flwd_fwd_idle_call.c create mode 100644 src/forward/flwd_fwd_maat.c create mode 100644 src/packet_io/Makefile create mode 100644 src/packet_io/flwd_io_pcap.so create mode 100644 src/packet_io/flwd_io_socket.so create mode 100644 src/packet_io/flwd_packet_io.c create mode 100644 src/packet_io/flwd_packet_io_pcap.c create mode 100644 src/packet_io/flwd_packet_io_socket.c create mode 100644 src/packet_io/nf-queue.c create mode 100644 src/packet_io/nfq_test.c create mode 100644 support/include/MESA_atomic_for_view.h create mode 100644 support/include/MESA_handle_logger_for_view.h create mode 100644 support/include/MESA_htable_for_view.h create mode 100644 support/include/MESA_list_count_for_view.h create mode 100644 support/include/MESA_list_for_view.h create mode 100644 support/include/MESA_list_queue_for_view.h create mode 100644 support/include/MESA_prof_load_for_view.h create mode 100644 support/include/MESA_ring_queue_for_view.h create mode 100644 support/include/Maat_command_for_view.h create mode 100644 support/include/Maat_rule_for_view.h create mode 100644 support/include/field_stat2_for_view.h create mode 100644 "support/include/\346\234\254\346\226\207\344\273\266\345\244\271\344\270\255\347\232\204\346\226\207\344\273\266\344\273\205\347\224\250\344\272\216\346\237\245\347\234\213_\344\270\215\347\274\226\350\257\221.txt" create mode 100644 support/ltsm/Makefile create mode 100644 support/ltsm/ltsm.c create mode 100644 support/ltsm/ltsm.h create mode 100644 support/ltsm/ltsm_with_hash.h create mode 100644 support/ltsm/test_ltsm.c create mode 100644 test/mutex_vs_rdlock.c create mode 100644 test/sport_usable.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..27ce0e6 --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +__YES=1 +__NO=0 +TYPE_ACCESS=access +TYPE_FORWARD=forward +type= +__MAKE_CHECK=$(__NO) +CFLAGS= + +ifeq ($(type), $(TYPE_ACCESS)) + __MAKE_CHECK = $(__YES) + CFLAGS += -DCOMPILE_ACCESS=1 +endif + +ifeq ($(type), $(TYPE_FORWARD)) + __MAKE_CHECK = $(__YES) + CFLAGS += -DCOMPILE_FORWARD=1 +endif + +ifeq ($(__MAKE_CHECK), $(__NO)) + $(error must assign type use make type=[access|forward]!) + exit +endif + +export CFLAGS +export type +export TYPE_ACCESS +export TYPE_FORWARD + +all: + cd support/ltsm; $(MAKE); + cd src/access; $(MAKE); + cd src/common; $(MAKE); + cd src/packet_io; $(MAKE); + cd src/forward; $(MAKE); + cd src; $(MAKE); + +clean: + cd src/access; $(MAKE) clean; + cd src/common; $(MAKE) clean; + cd src/packet_io; $(MAKE) clean; + cd src/forward; $(MAKE) clean; + cd src; $(MAKE) clean; + cd support/ltsm; $(MAKE) clean; + rm -f bin/flowood_access bin/flowood_forward diff --git a/bin/conf/flowood.conf b/bin/conf/flowood.conf new file mode 100644 index 0000000..d270e7e --- /dev/null +++ b/bin/conf/flowood.conf @@ -0,0 +1,62 @@ +[main] +thread_num=1 +nat_htable_timeout=180 +nat_htable_max_num=10000 +global_access_gateway_num = 5 +#id start with natural number, 1 +current_access_gateway_id = 2 + +use_static_pool_ip_if_no_dynamic=0 +use_dynamic_pool_ip_if_no_static=0 + +[log] +log_level=10 + +[maat] +json_switch=1 +json_cfg_file=./conf/maat_test.json +table_info=./conf/maat_tableinfo.conf +inc_dir=./soqrule/inc/index/ +full_dir=./soqrule/full/index/ + + +#cap_mode: (0:pag,1:pcap,2:socket,3:pfring,4:DPDK,5:ppf,6:NPacket,7:qnf,8:N95,9:pcap-dumpfile-list,10:topsec +# 11:ipfile, 12:marsio4, 13:agent_smith, 14:dpdk_vxlan, 15:marsio_vxlan, 16:pag_marsio) +# for flowood, only support mode1, mode2, mode12! + +[TOPO_ACC_LINK_USER] +cap_mode=1 +device_name=em1 +addr_para=172.18.1.229 +addr_mask=255.255.0.0 +gateway_ip=172.18.1.254 +pkt_filter=net 172.18.0.0/16 + + +[TOPO_ACC_LINK_FWD] +cap_mode=2 +device_name=em2 +addr_para=64789 +#addr_para=172.16.1.229 +#addr_mask=255.255.255.0 +gateway_ip=192.168.10.1 +pkt_filter= + +[TOPO_FWD_LINK_ACC] +cap_mode=2 +device_name=em1sdf +addr_para=64789 +#addr_para=172.16.1.201 +#addr_mask=255.255.0.0 +gateway_ip=172.16.1.201 +pkt_filter=net 172.16.0.0/16 + + +[TOPO_FWD_LINK_GDEV] +cap_mode=1 +device_name=em1 +addr_para=172.17.1.203 +addr_mask=255.255.0.0 +gateway_ip=172.17.1.1 +pkt_filter=net 172.17.0.0/16 + diff --git a/bin/conf/maat_tableinfo.conf b/bin/conf/maat_tableinfo.conf new file mode 100644 index 0000000..6d935bd --- /dev/null +++ b/bin/conf/maat_tableinfo.conf @@ -0,0 +1,16 @@ +#each collumn seperate with '\t' +#id (0~65535) +#name string +#type one of ip,expr,expr_plus,digest,intval,compile or plugin +#src_charset one of GBK,BIG5,UNICODE,UTF8 +#dst_charset combined by GBK,BIG5,UNICODE,UTF8,seperate with '/' +#do_merege yes or no +#cross cache 0~max +#quickswitch quickon or quick off +#id name type src_charset dst_charset do_merge cross_cache quickswitch +0 IR_POLICY_COMPILE compile UTF8 UTF8 no 0 +1 IR_POLICY_GROUP group UTF8 UTF8 no 0 +2 IR_POLICY_IP ip UTF8 UTF8 no 0 +3 IR_STATIC_IP_POOL_CB plugin UTF8 UTF8 no 0 +4 IR_DYN_SIFT_IP_CB plugin UTF8 UTF8 no 0 +5 IR_DYN_CONN_IP ip -- diff --git a/bin/conf/maat_test.json b/bin/conf/maat_test.json new file mode 100644 index 0000000..9be798c --- /dev/null +++ b/bin/conf/maat_test.json @@ -0,0 +1,89 @@ +{ + "compile_table": "IR_POLICY_COMPILE", + "group_table": "IR_POLICY_GROUP", + "rules": [ + { + "compile_id": 1, + "service": 1, + "action": 2, + "do_blacklist": 1, + "do_log": 1, + "effective_rage": 0, + "user_region": "IR_STRATEGY:10001", + "is_valid": "yes", + "groups": [ + { + "group_name": "group_1", + "regions": [ + { + "table_name": "IR_POLICY_IP", + "table_type": "ip", + "table_content": { + "addr_type": "ipv4", + "src_ip": "172.18.1.13", + "mask_src_ip": "255.255.255.255", + "src_port": "0", + "mask_src_port": "65535", + "dst_ip": "0.0.0.0", + "mask_dst_ip": "255.255.255.255", + "dst_port": "0", + "mask_dst_port": "65535", + "protocol": 0, + "direction": "double" + } + } + ] + } + ] + }, + { + "compile_id": 2, + "service": 1, + "action": 2, + "do_blacklist": 1, + "do_log": 1, + "effective_rage": 0, + "user_region": "IR_STRATEGY:10002", + "is_valid": "yes", + "groups": [ + { + "group_name": "group_2", + "regions": [ + { + "table_name": "IR_POLICY_IP", + "table_type": "ip", + "table_content": { + "addr_type": "ipv4", + "src_ip": "172.18.1.222", + "mask_src_ip": "255.255.255.255", + "src_port": "0", + "mask_src_port": "65535", + "dst_ip": "0.0.0.0", + "mask_dst_ip": "255.255.255.255", + "dst_port": "0", + "mask_dst_port": "65535", + "protocol": 0, + "direction": "double" + } + } + ] + } + ] + } + ], + "plugin_table": [ + { + "table_name": "IR_DYN_SIFT_IP_CB", + "table_content": [ + "1\t4\t0\t192.168.10.222\t0\t2\tgdev_ip=10.0.6.195;\t0\t1\t2018-07-15" + ] + }, + { + "table_name": "IR_STATIC_IP_POOL_CB", + "table_content": [ + "1\t4\t0\t47.74.128.220\t0\t2\tgdev_ip=10.0.6.195;\t0\t1\t1\t1\t10001\t2018-07-15", + "2\t4\t0\t192.168.10.222\t0\t2\tgdev_ip=10.0.6.195;\t0\t1\t1\t1\t10002\t2018-07-15" + ] + } + ] +} diff --git a/bin/conf/maat_test.json_iris_tmp/IR_DYN_SIFT_IP_CB.local b/bin/conf/maat_test.json_iris_tmp/IR_DYN_SIFT_IP_CB.local new file mode 100644 index 0000000..2fc8e5f --- /dev/null +++ b/bin/conf/maat_test.json_iris_tmp/IR_DYN_SIFT_IP_CB.local @@ -0,0 +1,2 @@ +0000000001 +1 4 0 192.168.10.222 0 2 gdev_ip=10.0.6.195; 0 1 2018-07-15 diff --git a/bin/conf/maat_test.json_iris_tmp/IR_POLICY_COMPILE.local b/bin/conf/maat_test.json_iris_tmp/IR_POLICY_COMPILE.local new file mode 100644 index 0000000..f0d8445 --- /dev/null +++ b/bin/conf/maat_test.json_iris_tmp/IR_POLICY_COMPILE.local @@ -0,0 +1,3 @@ +0000000002 +1 1 2 1 1 0 IR_STRATEGY:10001 1 +2 1 2 1 1 0 IR_STRATEGY:10002 1 diff --git a/bin/conf/maat_test.json_iris_tmp/IR_POLICY_GROUP.local b/bin/conf/maat_test.json_iris_tmp/IR_POLICY_GROUP.local new file mode 100644 index 0000000..86bfaf1 --- /dev/null +++ b/bin/conf/maat_test.json_iris_tmp/IR_POLICY_GROUP.local @@ -0,0 +1,3 @@ +0000000002 +0 1 1 +1 2 1 diff --git a/bin/conf/maat_test.json_iris_tmp/IR_POLICY_IP.local b/bin/conf/maat_test.json_iris_tmp/IR_POLICY_IP.local new file mode 100644 index 0000000..57f5ad9 --- /dev/null +++ b/bin/conf/maat_test.json_iris_tmp/IR_POLICY_IP.local @@ -0,0 +1,3 @@ +0000000002 +0 0 4 172.18.1.13 255.255.255.255 0 65535 0.0.0.0 255.255.255.255 0 65535 0 0 1 +1 1 4 172.18.1.222 255.255.255.255 0 65535 0.0.0.0 255.255.255.255 0 65535 0 0 1 diff --git a/bin/conf/maat_test.json_iris_tmp/IR_STATIC_IP_POOL_CB.local b/bin/conf/maat_test.json_iris_tmp/IR_STATIC_IP_POOL_CB.local new file mode 100644 index 0000000..874147d --- /dev/null +++ b/bin/conf/maat_test.json_iris_tmp/IR_STATIC_IP_POOL_CB.local @@ -0,0 +1,3 @@ +0000000002 +1 4 0 47.74.128.220 0 2 gdev_ip=10.0.6.195; 0 1 1 1 10001 2018-07-15 +2 4 0 192.168.10.222 0 2 gdev_ip=10.0.6.195; 0 1 1 1 10002 2018-07-15 diff --git a/bin/conf/maat_test.json_iris_tmp/index/full_config_index.0000000001 b/bin/conf/maat_test.json_iris_tmp/index/full_config_index.0000000001 new file mode 100644 index 0000000..ba4e23c --- /dev/null +++ b/bin/conf/maat_test.json_iris_tmp/index/full_config_index.0000000001 @@ -0,0 +1,5 @@ +IR_POLICY_COMPILE 2 ./conf/maat_test.json_iris_tmp/IR_POLICY_COMPILE.local +IR_POLICY_GROUP 2 ./conf/maat_test.json_iris_tmp/IR_POLICY_GROUP.local +IR_DYN_SIFT_IP_CB 1 ./conf/maat_test.json_iris_tmp/IR_DYN_SIFT_IP_CB.local +IR_STATIC_IP_POOL_CB 2 ./conf/maat_test.json_iris_tmp/IR_STATIC_IP_POOL_CB.local +IR_POLICY_IP 2 ./conf/maat_test.json_iris_tmp/IR_POLICY_IP.local diff --git a/bin/conf/network_access.cfg b/bin/conf/network_access.cfg new file mode 100644 index 0000000..f88daa0 --- /dev/null +++ b/bin/conf/network_access.cfg @@ -0,0 +1,4 @@ +#global_id access_manage_ip access_feedback_ip +#for example: +1 10.0.6.229 172.16.0.229 +1 10.0.6.203 172.16.0.203 diff --git a/bin/conf/network_connect.cfg b/bin/conf/network_connect.cfg new file mode 100644 index 0000000..23f5b9c --- /dev/null +++ b/bin/conf/network_connect.cfg @@ -0,0 +1,6 @@ +#region vlan_id gdev_redirect_ip forward_manage_ip forward_feedback_ip +#for example: +#beijing 1 10.0.0.1 10.0.0.101 172.16.0.1 +#shanghai 1 10.0.1.1 10.0.1.103 172.16.1.3 +#guangzhou 1 10.0.2.3 10.0.2.101 172.16.2.1 +alamutu 1 10.0.6.201 10.0.6.201 10.0.6.201 diff --git a/bin/conf/network_forward.cfg b/bin/conf/network_forward.cfg new file mode 100644 index 0000000..e41d4a5 --- /dev/null +++ b/bin/conf/network_forward.cfg @@ -0,0 +1,6 @@ +#region vlan_id forward_ip +#for example: +#beijing 1 10.0.0.101 +#shanghai 1 10.0.1.103 +#guangzhou 1 10.0.2.101 +huayan 1 10.0.6.201 diff --git a/bin/conf/network_gdev.cfg b/bin/conf/network_gdev.cfg new file mode 100644 index 0000000..f57988d --- /dev/null +++ b/bin/conf/network_gdev.cfg @@ -0,0 +1,6 @@ +#region vlan_id gdev_redirect_ip +#for example: +#beijing 1 10.0.0.1 +#shanghai 1 10.0.1.1 +#guangzhou 1 10.0.2.3 +huayan 1 10.0.6.195 diff --git a/bin/flowood_keepalive.py b/bin/flowood_keepalive.py new file mode 100644 index 0000000..9fbf312 --- /dev/null +++ b/bin/flowood_keepalive.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +# 因某些NAT, 外网出口源端口会变化, 即便绑定了客户端的源端口也不行 +# 所以使用一个脚本, 让数据包源源不断的发送, 就可以维持住NAT的连接表, +# +from scapy import * +from scapy.all import * +import random + +while 1: + ip_pkt = IP(dst='47.75.205.197',src='192.168.10.214') + udp_pkt = UDP(dport=64789,sport=64789) + #dns_pkt = DNS(id=1,qr=0,opcode=0,tc=0,rd=1,qdcount=1,ancount=0,nscount=0,arcount=0) + #dns_pkt.qd=DNSQR(qname='www.keepalive.com',qtype=255,qclass=1) + #send_pkt = ip_pkt/udp_pkt/dns_pkt + payload = 'test'; + send_pkt = ip_pkt/udp_pkt/payload + send(send_pkt) + time.sleep(0.33) +pass \ No newline at end of file diff --git a/bin/flwd_r2 b/bin/flwd_r2 new file mode 100644 index 0000000..dcdcbb8 --- /dev/null +++ b/bin/flwd_r2 @@ -0,0 +1,3 @@ +killall flwd_r3 flowood_access +./flwd_r3 &> /dev/null & +#./kill_sapp_by_mem.sh &> /dev/null & diff --git a/bin/flwd_r3 b/bin/flwd_r3 new file mode 100644 index 0000000..45b7d54 --- /dev/null +++ b/bin/flwd_r3 @@ -0,0 +1,17 @@ +#!/bin/sh + +while [ 1 ]; do + count=`ls -l core.* |wc -l` + echo $count + if [ $count -lt 5 ] + then + echo "set unlimited" + ulimit -c unlimited + else + ulimit -c 0 + fi + + ./flowood_access > /dev/null + echo program crashed, restart at `date +"%w %Y/%m/%d, %H:%M:%S"` >> RESTART.log + sleep 10 +done diff --git a/bin/io_lib/flwd_io_pcap.so b/bin/io_lib/flwd_io_pcap.so new file mode 100644 index 0000000..7af3822 Binary files /dev/null and b/bin/io_lib/flwd_io_pcap.so differ diff --git a/bin/io_lib/flwd_io_socket.so b/bin/io_lib/flwd_io_socket.so new file mode 100644 index 0000000..7db273b Binary files /dev/null and b/bin/io_lib/flwd_io_socket.so differ diff --git a/bin/memchk.sh b/bin/memchk.sh new file mode 100644 index 0000000..5ce6bfb --- /dev/null +++ b/bin/memchk.sh @@ -0,0 +1,2 @@ +#!/bin/sh +valgrind --tool=memcheck --leak-check=full --leak-resolution=high --error-limit=no --undef-value-errors=yes --log-file=valgrind.log $1 diff --git a/bin/rulescan_tmp/rulescan_iie.log b/bin/rulescan_tmp/rulescan_iie.log new file mode 100644 index 0000000..e69de29 diff --git a/deploy.txt b/deploy.txt new file mode 100644 index 0000000..66a32fe --- /dev/null +++ b/deploy.txt @@ -0,0 +1,13 @@ +#if 0 +1)ڲIR + ΪԻڵCζǺϷõ, ֹͨļ, ģmaat_cb, + dynamic_ip_pool_cb, ļеIPֵ̬IP + + +2)IR + õĵַIPDzԻCIP, + ͨmaat_redisɻȡĿǰûԶ־SMAC=xxxֶΣȡGDEVϢ + ֳֻͨȻԼstatic_ip_pool_cbһSMAC=xxxx. + +#endif + diff --git a/deploy/ethtool b/deploy/ethtool new file mode 100644 index 0000000..f16b4bb --- /dev/null +++ b/deploy/ethtool @@ -0,0 +1,3 @@ +ethtool -K eth0 gso off +ethtool -K eth0 gro off +ethtool -K eth0 tso off diff --git a/deploy/ip_forward b/deploy/ip_forward new file mode 100644 index 0000000..3f15c3b --- /dev/null +++ b/deploy/ip_forward @@ -0,0 +1 @@ +echo "1" > /proc/sys/net/ipv4/ip_forward diff --git a/deploy/iptable_drop_rst b/deploy/iptable_drop_rst new file mode 100644 index 0000000..30b6224 --- /dev/null +++ b/deploy/iptable_drop_rst @@ -0,0 +1 @@ +iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP diff --git a/deploy/l2tp/xl2tpd-1.3.8-8.fc29.x86_64.rpm b/deploy/l2tp/xl2tpd-1.3.8-8.fc29.x86_64.rpm new file mode 100644 index 0000000..a3b67b9 Binary files /dev/null and b/deploy/l2tp/xl2tpd-1.3.8-8.fc29.x86_64.rpm differ diff --git a/deploy/pptpd/pptpd_install/auth-down b/deploy/pptpd/pptpd_install/auth-down new file mode 100644 index 0000000..81e2228 --- /dev/null +++ b/deploy/pptpd/pptpd_install/auth-down @@ -0,0 +1,7 @@ +#!/bin/bash +# get the username from the parameters +USER=$2 +# if there is a session already for this user, terminate the old one +rm -f /var/run/ppp/current_user/$USER +echo $2 link down ! >> /var/run/ppp/user_access.log + diff --git a/deploy/pptpd/pptpd_install/auth-up b/deploy/pptpd/pptpd_install/auth-up new file mode 100644 index 0000000..d8a2c75 --- /dev/null +++ b/deploy/pptpd/pptpd_install/auth-up @@ -0,0 +1,19 @@ +#!/bin/bash +# get the username from the parameters +USER=$2 +# if there is a session already for this user, terminate the old one + +mkdir -p /var/run/ppp/current_user/ + +PPID=`awk '/PPid/ { print $2; }' /proc/$$/status` + +if [ -f /var/run/ppp/current_user/$USER ]; then + echo $2 already access success, exit, pid:$$, ppid:$PPID >> /var/run/ppp/user_access.log + kill -9 $PPID +else + echo $2 > /var/run/ppp/current_user/$USER + echo $2 dial up success! >> /var/run/ppp/user_access.log +fi + + + diff --git a/deploy/pptpd/pptpd_install/chap-secrets b/deploy/pptpd/pptpd_install/chap-secrets new file mode 100644 index 0000000..d27529d --- /dev/null +++ b/deploy/pptpd/pptpd_install/chap-secrets @@ -0,0 +1,58 @@ +# Secrets for authentication using CHAP +# client server secret IP addresses +mesa pptpd 111111 * +liuqingyun_hk pptpd 111111 172.18.1.101 +zhengchao_hk pptpd 111111 172.18.1.102 +yangrong_hk pptpd 111111 172.18.1.103 +zhouzhou_hk pptpd 111111 172.18.1.104 +lijia_hk pptpd 111111 172.18.1.105 +doufenghu_hk pptpd 111111 172.18.1.106 +dumeijie_hk pptpd 111111 172.18.1.107 +fengweihao_hk pptpd 111111 172.18.1.108 +guofu_hk pptpd 111111 172.18.1.109 +jixinyi_hk pptpd 111111 172.18.1.110 +lishu_hk pptpd 111111 172.18.1.111 +lizhao_hk pptpd 111111 172.18.1.111 +liujunpeng_hk pptpd 111111 172.18.1.112 +liuxueli_hk pptpd 111111 172.18.1.113 +liuyang_hk pptpd 111111 172.18.1.114 +luqiuwen_hk pptpd 111111 172.18.1.115 +qidaijie_hk pptpd 111111 172.18.1.116 +wangfengmei_hk pptpd 111111 172.18.1.117 +wangkuan_hk pptpd 111111 172.18.1.118 +wangyouzhan_hk pptpd 111111 172.18.1.119 +yangwei_hk pptpd 111111 172.18.1.120 +yulingjing_hk pptpd 111111 172.18.1.121 +zhangchengwei_hk pptpd 111111 172.18.1.122 +zhanglei_hk pptpd 111111 172.18.1.123 +zhangpeng_hk pptpd 111111 172.18.1.124 +jiamengdie_hk pptpd 111111 172.18.1.125 +zhuyujia_hk pptpd 111111 172.18.1.126 + +liuqingyun_de pptpd 111111 172.18.1.131 +zhengchao_de pptpd 111111 172.18.1.132 +yangrong_de pptpd 111111 172.18.1.133 +zhouzhou_de pptpd 111111 172.18.1.134 +lijia_de pptpd 111111 172.18.1.135 +doufenghu_de pptpd 111111 172.18.1.136 +dumeijie_de pptpd 111111 172.18.1.137 +fengweihao_de pptpd 111111 172.18.1.138 +guofu_de pptpd 111111 172.18.1.139 +jixinyi_de pptpd 111111 172.18.1.140 +lishu_de pptpd 111111 172.18.1.141 +lizhao_de pptpd 111111 172.18.1.142 +liujunpeng_de pptpd 111111 172.18.1.143 +liuxueli_de pptpd 111111 172.18.1.144 +liuyang_de pptpd 111111 172.18.1.145 +luqiuwen_de pptpd 111111 172.18.1.146 +qidaijie_de pptpd 111111 172.18.1.147 +wangfengmei_de pptpd 111111 172.18.1.148 +wangkuan_de pptpd 111111 172.18.1.149 +wangyouzhan_de pptpd 111111 172.18.1.150 +yangwei_de pptpd 111111 172.18.1.151 +yulingjing_de pptpd 111111 172.18.1.152 +zhangchengwei_de pptpd 111111 172.18.1.153 +zhanglei_de pptpd 111111 172.18.1.154 +zhangpeng_de pptpd 111111 172.18.1.155 +jiamengdie_de pptpd 111111 172.18.1.156 +zhuyujia_de pptpd 111111 172.18.1.157 diff --git a/deploy/pptpd/pptpd_install/options.pptpd b/deploy/pptpd/pptpd_install/options.pptpd new file mode 100644 index 0000000..738c10f --- /dev/null +++ b/deploy/pptpd/pptpd_install/options.pptpd @@ -0,0 +1,134 @@ +############################################################################### +# $Id: options.pptpd,v 1.11 2005/12/29 01:21:09 quozl Exp $ +# +# Sample Poptop PPP options file /etc/ppp/options.pptpd +# Options used by PPP when a connection arrives from a client. +# This file is pointed to by /etc/pptpd.conf option keyword. +# Changes are effective on the next connection. See "man pppd". +# +# You are expected to change this file to suit your system. As +# packaged, it requires PPP 2.4.2 and the kernel MPPE module. +############################################################################### + + +# Authentication + +# Name of the local system for authentication purposes +# (must match the second field in /etc/ppp/chap-secrets entries) +name pptpd + +# Strip the domain prefix from the username before authentication. +# (applies if you use pppd with chapms-strip-domain patch) +#chapms-strip-domain + + +# Encryption +# (There have been multiple versions of PPP with encryption support, +# choose with of the following sections you will use.) + + +# BSD licensed ppp-2.4.2 upstream with MPPE only, kernel module ppp_mppe.o +# {{{ +refuse-pap +refuse-chap +refuse-mschap +# Require the peer to authenticate itself using MS-CHAPv2 [Microsoft +# Challenge Handshake Authentication Protocol, Version 2] authentication. +require-mschap-v2 +# Require MPPE 128-bit encryption +# (note that MPPE requires the use of MSCHAP-V2 during authentication) +require-mppe-128 +# }}} + + +# OpenSSL licensed ppp-2.4.1 fork with MPPE only, kernel module mppe.o +# {{{ +#-chap +#-chapms +# Require the peer to authenticate itself using MS-CHAPv2 [Microsoft +# Challenge Handshake Authentication Protocol, Version 2] authentication. +#+chapms-v2 +# Require MPPE encryption +# (note that MPPE requires the use of MSCHAP-V2 during authentication) +#mppe-40 # enable either 40-bit or 128-bit, not both +#mppe-128 +#mppe-stateless +# }}} + + +# Network and Routing + +# If pppd is acting as a server for Microsoft Windows clients, this +# option allows pppd to supply one or two DNS (Domain Name Server) +# addresses to the clients. The first instance of this option +# specifies the primary DNS address; the second instance (if given) +# specifies the secondary DNS address. +#ms-dns 10.0.0.1 +#ms-dns 10.0.0.2 +ms-dns 8.8.8.8 + +# If pppd is acting as a server for Microsoft Windows or "Samba" +# clients, this option allows pppd to supply one or two WINS (Windows +# Internet Name Services) server addresses to the clients. The first +# instance of this option specifies the primary WINS address; the +# second instance (if given) specifies the secondary WINS address. +#ms-wins 10.0.0.3 +#ms-wins 10.0.0.4 + +# Add an entry to this system's ARP [Address Resolution Protocol] +# table with the IP address of the peer and the Ethernet address of this +# system. This will have the effect of making the peer appear to other +# systems to be on the local ethernet. +# (you do not need this if your PPTP server is responsible for routing +# packets to the clients -- James Cameron) +proxyarp + +# Normally pptpd passes the IP address to pppd, but if pptpd has been +# given the delegate option in pptpd.conf or the --delegate command line +# option, then pppd will use chap-secrets or radius to allocate the +# client IP address. The default local IP address used at the server +# end is often the same as the address of the server. To override this, +# specify the local IP address here. +# (you must not use this unless you have used the delegate option) +#10.8.0.100 + + +# Logging + +# Enable connection debugging facilities. +# (see your syslog configuration for where pppd sends to) +#debug + +# Print out all the option values which have been set. +# (often requested by mailing list to verify options) +#dump + + +# Miscellaneous + +# Create a UUCP-style lock file for the pseudo-tty to ensure exclusive +# access. +lock + +# Disable BSD-Compress compression +nobsdcomp + +# Disable Van Jacobson compression +# (needed on some networks with Windows 9x/ME/XP clients, see posting to +# poptop-server on 14th April 2005 by Pawel Pokrywka and followups, +# http://marc.theaimsgroup.com/?t=111343175400006&r=1&w=2 ) +novj +novjccomp + +# turn off logging to stderr, since this may be redirected to pptpd, +# which may trigger a loopback +nologfd + +# put plugins here +# (putting them higher up may cause them to sent messages to the pty) + +mru 1380 +mtu 1380 +holdoff 10 +idle 60 + diff --git a/deploy/pptpd/pptpd_install/pptpd-1.4.0-2.el7.x86_64.rpm b/deploy/pptpd/pptpd_install/pptpd-1.4.0-2.el7.x86_64.rpm new file mode 100644 index 0000000..48c8946 Binary files /dev/null and b/deploy/pptpd/pptpd_install/pptpd-1.4.0-2.el7.x86_64.rpm differ diff --git a/deploy/pptpd/pptpd_install/pptpd.conf b/deploy/pptpd/pptpd_install/pptpd.conf new file mode 100644 index 0000000..6ebc63c --- /dev/null +++ b/deploy/pptpd/pptpd_install/pptpd.conf @@ -0,0 +1,106 @@ +############################################################################### +# $Id: pptpd.conf,v 1.11 2011/05/19 00:02:50 quozl Exp $ +# +# Sample Poptop configuration file /etc/pptpd.conf +# +# Changes are effective when pptpd is restarted. +############################################################################### + +# TAG: ppp +# Path to the pppd program, default '/usr/sbin/pppd' on Linux +# +#ppp /usr/sbin/pppd + +# TAG: option +# Specifies the location of the PPP options file. +# By default PPP looks in '/etc/ppp/options' +# +option /etc/ppp/options.pptpd + +# TAG: debug +# Turns on (more) debugging to syslog +# +#debug + +# TAG: stimeout +# Specifies timeout (in seconds) on starting ctrl connection +# +# stimeout 10 + +# TAG: noipparam +# Suppress the passing of the client's IP address to PPP, which is +# done by default otherwise. +# +#noipparam + +# TAG: logwtmp +# Use wtmp(5) to record client connections and disconnections. +# +logwtmp + +# TAG: vrf +# Switches PPTP & GRE sockets to the specified VRF, which must exist +# Only available if VRF support was compiled into pptpd. +# +#vrf test + +# TAG: bcrelay +# Turns on broadcast relay to clients from interface +# +#bcrelay eth1 + +# TAG: delegate +# Delegates the allocation of client IP addresses to pppd. +# +# Without this option, which is the default, pptpd manages the list of +# IP addresses for clients and passes the next free address to pppd. +# With this option, pptpd does not pass an address, and so pppd may use +# radius or chap-secrets to allocate an address. +# +#delegate + +# TAG: connections +# Limits the number of client connections that may be accepted. +# +# If pptpd is allocating IP addresses (e.g. delegate is not +# used) then the number of connections is also limited by the +# remoteip option. The default is 100. +#connections 100 + +# TAG: localip +# TAG: remoteip +# Specifies the local and remote IP address ranges. +# +# These options are ignored if delegate option is set. +# +# Any addresses work as long as the local machine takes care of the +# routing. But if you want to use MS-Windows networking, you should +# use IP addresses out of the LAN address space and use the proxyarp +# option in the pppd options file, or run bcrelay. +# +# You can specify single IP addresses seperated by commas or you can +# specify ranges, or both. For example: +# +# 192.168.0.234,192.168.0.245-249,192.168.0.254 +# +# IMPORTANT RESTRICTIONS: +# +# 1. No spaces are permitted between commas or within addresses. +# +# 2. If you give more IP addresses than the value of connections, +# it will start at the beginning of the list and go until it +# gets connections IPs. Others will be ignored. +# +# 3. No shortcuts in ranges! ie. 234-8 does not mean 234 to 238, +# you must type 234-238 if you mean this. +# +# 4. If you give a single localIP, that's ok - all local IPs will +# be set to the given one. You MUST still give at least one remote +# IP for each simultaneous client. +# +# (Recommended) +localip 172.18.1.254 +#remoteip 192.168.0.234-238,192.168.0.245 +# or +#localip 192.168.0.234-238,192.168.0.245 +remoteip 172.18.1.100-200 diff --git a/deploy/pptpd/pptpd_install/pptpd.install.sh b/deploy/pptpd/pptpd_install/pptpd.install.sh new file mode 100644 index 0000000..365939c --- /dev/null +++ b/deploy/pptpd/pptpd_install/pptpd.install.sh @@ -0,0 +1,16 @@ +#!/bin/sh +rpm -ivh ./pptpd-1.4.0-2.el7.x86_64.rpm + +cp pptpd.conf /etc +cp options.pptpd /etc/ppp/ +cp chap-secrets /etc/ppp/ +cp auth-down /etc/ppp +cp auth-up /etc/ppp + +service pptpd restart + + + + + + diff --git a/deploy/problem b/deploy/problem new file mode 100644 index 0000000..0132ad8 --- /dev/null +++ b/deploy/problem @@ -0,0 +1,2 @@ +1-YiZhuang NAT use PNAT, modiyf source port per link; +2-maybe the WIFI don't allow GRE packet, so PPTP can't established! diff --git a/deploy/user_pass b/deploy/user_pass new file mode 100644 index 0000000..83796f8 --- /dev/null +++ b/deploy/user_pass @@ -0,0 +1,8 @@ +Ali_IP:47.91.74.214:22 +user: mesa +pass:mesalab2018@AV + + +Ali_IP: 47.75.205.197 +user: root +pass: MESA@LiJia#20170808 diff --git a/inc/flowood.h b/inc/flowood.h new file mode 100644 index 0000000..74f77c4 --- /dev/null +++ b/inc/flowood.h @@ -0,0 +1,491 @@ +#ifndef _FLOWOOD_H_ +#define _FLOWOOD_H_ 1 +#include +#include +#include +#include +#include +#include +#include "MESA_htable.h" +#include "MESA_list_queue.h" +#include "MESA_atomic.h" +#include "MESA_handle_logger.h" +#include "MESA_prof_load.h" +#include "MESA_list_count.h" +#include "MESA_list.h" +#include "stream.h" + + +#define FLWD_RUN_AS_SAPP_PLUG (1) /* תsappIJʽ */ +#define FLWD_NO_ACTIVE_IP_DISCOVER (0) /* ûлԾIPϵͳ, ָֹһЩip, Բ */ +#define FLWD_NO_GDEV_ENV (0) /* ûGDEVĻ, תģ·ģʽ, ͸ת, ʵҪڲԽع */ +#define FLWD_NO_ACTIVE_ARP_QUERY (0) /* ûARPѯ, Эջģ, raw_socket, marsioԭʼӿ, ҪֶָMACַ */ +#define FLWD_NO_MAAT (0) +#define FLWD_SUPPORT_DNAT (0) /* DNATȲʵ! */ +#define FLWD_ASYNC_LOCK_FREE (0) /* 첽ģʽ̸߳ */ +#define FLWD_IP_REGION_BY_LIB (0) /* 1:IPĵλϢIPַѯõ; 0:IPλϢֹúͶ̬ϵͳ, ˵ɶɶ */ +#define FLWD_USE_LTSM_FOR_QUICK_CLOSE (0) /* ʹLTSMǿʱ̭, ԾTCP, Իտö˿ */ + +#define FLWD_NAT_SPORT_VOLATILE (0) /* accessNATڲʱ, Դ˿ڻ仯, accessԴ˿Ҳ, ʱҪforwardҲ¼յʱԴ˿, ޷ */ + +#define FLWD_RUN_IN_CEIEC_TEST (1) /* ceiecԻʱдIJ */ + +#define FLWD_USE_SPORT_HASH_AS_MARK (1) /* ʹԴ˿ڵijЩbitλ, ڱʶacc-gateway, hashֵ, fwd-gatewayȷش̨acc-gateway */ +/* + ʹʱbitֲλ: + |15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0| + |accid| hash | sport | + + 2bit id; + м6bit HASHֵ; + 8bit Ŀö˿; +*/ +#if FLWD_USE_SPORT_HASH_AS_MARK +#define FLWD_SPORT_ACC_ID_MASK (0xC000) /* , acc-gateway ID, λbit, ͬһֵ֧4̨acc-gateway豸 */ +#define FLWD_SPORT_ACC_ID_SHIFT_NUM (14) /* MASKƶ14λ, , ǰֵID */ + +#define FLWD_UDP_SPORT_HASH_MASK (0x3F00) /* , hashֵ,ڸʵ, 6bit, Ԫͻʶ׼ȷ: 98.4%, Ǹÿͻ˺ʵͻͬʱһʶ */ +#define FLWD_UDP_SPORT_ACTUAL_PORT_MASK (0x00FF) /* , ʵö˿ڵֵ, 8bit. ʵҲ10bit, ټacc-gateway id */ +#define FLWD_TCP_SPORT_ACTUAL_PORT_MASK (FLWD_UDP_SPORT_ACTUAL_PORT_MASK) /* TODO, Ժ, TCPɲʹö˿HASHΪ, ISN±,ӿö˿ڷΧ */ +#else + +#endif + + +#define FLWD_LINK_MTU (2048) +#define FLWD_MAX_THREAD_NUM (64) +#define FLWD_REGION_STR_LEN_MAX (32) /* ֵ */ +#define FLWD_NETWORK_NxM_MAX (16) /* GDEVת֮ NxM 豸ֵ */ + +#define TRAFFIC_STAT_STR_LEN (32) + +#define FLWD_CONFIG_FILE "./conf/ip_reuse/flowood.conf" + +#define FLWD_MACRO_TO_STRING(x) (#x) + + +/* ֧ѡŻ, еķ֧ж, ʹflwd_likely() */ +#ifndef flwd_likely +#define flwd_likely(x) __builtin_expect(!!(x), 1) +#endif + +#ifndef flwd_unlikely +#define flwd_unlikely(x) __builtin_expect(!!(x), 0) +#endif + +typedef enum{ + FLWD_DROP = 0, + FLWD_PASS = 1, +}flwd_pkt_action_t; + + +/* ֵÿҪӦ, ֹ޸ */ +typedef enum { + FLWD_NAT_TYPE_SNAT = 1, + FLWD_NAT_TYPE_DNAT = 2, +}flwd_nat_type_t; + + +typedef enum { + FLWD_IP_REGION_INLAND = 0, /* , ˶Ҫpanguݿһ!!! */ + FLWD_IP_REGION_OUTLAND = 1, /* , ˶Ҫpanguݿһ!!! */ + FLWD_IP_REGION_MAX = 2, +}flwd_ip_region_type_t; + + +typedef enum { + FLWD_ACT_IP_DYNAMIC = 1, /* ԶֵĶ̬ԾIP */ + FLWD_ACT_IP_STATIC = 2, /* ûͨ·ľ̬IPַ */ +}flwd_active_ip_type_t; + +/* NOTE: Ϊ˳ʹ±v4, v6, ˴4,6õʵֵ */ +typedef enum{ + FLWD_IP_ADDR_TYPE_V4 = 0, + FLWD_IP_ADDR_TYPE_V6 = 1, +}flwd_ip_addr_type_t; + + +typedef enum{ + FLWD_MAAT_SRC_JSON = 1, + FLWD_MAAT_SRC_LOCAL_FILE = 2, + FLWD_MAAT_SRC_REDIS = 3, +}flwd_maat_cfg_source_t; + + +typedef struct{ + unsigned char addr_type; + unsigned char addr_len; + unsigned short dport; /* NOTE: ṹҲ, ˴Ŀ϶һport, DNAT */ + union{ + unsigned int addr_ipv4; + struct in6_addr addr_ipv6; + unsigned char addr_value[16]; + }; +}flwd_ip_t; + + +typedef struct{ + unsigned int sip_net_order; + unsigned int dip_net_order; +}flwd_ippair_v4_t; + +typedef struct{ + struct in6_addr sip_net_order; + struct in6_addr dip_net_order; +}flwd_ippair_v6_t; + + +typedef struct{ + unsigned char addr_type; /* flwd_ip_addr_type_t, ÿԪʹöĵַ, Ԥv4_over_v6, v6_over_v4ĵַת */ + unsigned char protocol; /* TCPUDPԪҪ, Эֶ, ʵ5Ԫ */ + unsigned char dir_reverse; /* natת֮ǰkeyԪʵ, ǷݴַΪԴHASH淶, ˵ַת, : TCP_SYN, ֵΪ1, ˵key->dipSYNͷ, д־ʱע */ + unsigned char __pad; /* ֽڶ */ + unsigned short sport_net_order; + unsigned short dport_net_order; + union{ + flwd_ippair_v6_t *ippair_v6; /* ˴ʹָ, IPv6ַ̫, V6Խ, ˽ṹɺflwd_ippair_v4_tһ, unionԽԼڴ. עfree!! */ + flwd_ippair_v4_t ippair_v4; + }; +}flwd_tuple5_t; /* NATԪ */ + + +/* ʵIPͶ˿ */ +typedef struct{ + unsigned int actual_server_ip_net_order; + unsigned short actual_server_port_net_order; +}flwd_actual_ip_port_t; + + + +/* ݰԴ, or ת, + нת֮, Ԥsocketͨģʽ, Ϊ̿Բһ̨ +*/ +typedef enum { + TOPO_ACC_LINK_USER = 0, /* --ûն */ + TOPO_ACC_LINK_FWD = 1, /* --ת */ + TOPO_FWD_LINK_ACC = 2, /* ת-- */ + TOPO_FWD_LINK_GDEV = 3, /* ת--ר豸 */ + __TOPO_MODE_MAX = 4, +}flwd_topology_t; + +/* ûնЭ */ +typedef enum { + FLWD_TERMINAL_IP_LAYER, + FLWD_TERMINAL_IP_L2TP, + FLWD_TERMINAL_IP_PPTP, +}flwd_terminal_proto_t; + +typedef enum { + CAP_MODEL_PAG = 0, + CAP_MODEL_PCAP_ONLINE = 1, + CAP_MODEL_SOCKET = 2, /* ƽ̨, Ϊflowoodϵͳ϶öģʽ, ʵʱ, dumpfileΪsocketģʽ */ + CAP_MODEL_PFRING = 3, + CAP_MODEL_DPDK = 4, + CAP_MODEL_PPF = 5, + CAP_MODEL_NPACKET = 6, + CAP_MODEL_QNF = 7, /* for ߿ƼZhuanyong */ + CAP_MODEL_N95 = 8, /* to do: for xx9 UDP½ӿ */ + CAP_MODEL_PCAP_DUMPLIST = 9, /* 2014-11-19 lijia add */ + CAP_MODEL_TOPSEC = 10, /* 2015-09-29 lijia add, for trojan detect */ + CAP_MODEL_IPFILE = 11, + CAP_MODEL_MARSIOV4 = 12, /* 2016-10-26 lijia add, for DPDK-marsio-V4.0 */ + CAP_MODEL_AGENT_SMITH = 13, /* 2016-10-27 lijia add, for Դ빲ڴ */ + CAP_MODEL_DPDK_VXLAN = 14, /* 2016-11-01 lijia add, for DPDK-3.0, vxlan */ + CAP_MODEL_MARSIOV4_VXLAN= 15, /* 2016-11-01 lijia add, for MARSIO-4.0, vxlan */ + CAP_MODEL_PAG_MARSIO = 16, /* 2017-04-07 lijia add, for marsio compat pag */ + __CAP_MODEL_MAX = 17, +}flwd_cap_mode_t; + + +typedef enum{ + FLWD_OUTOPT_FIRST_PKT = 0x1, /* һװ, Ҫָ, accessͨvxlanֶθ֮fwd˰װ, fwdҪsession */ + +}flwd_output_opt_t; + + +typedef struct{ + void *low_level_mbuff; /* ײIOذṹ, : struct pfring_pkthdr, marsio_buff_t */ + char *inner_pkt_data; /* ڲMAC㿪ʼݲ */ + char *outer_pkt_data; /* MAC㿪ʼݲ */ + int inner_pkt_len; /* ڲMACͷʼݳ */ + int outer_pkt_len; /* MACͷʼݳ */ + flwd_terminal_proto_t terminal_proto; + const char *inner_ip_layer_hdr; /* Vxlan()ڲIPͷʼַ, v4 or v6 */ +}flwd_raw_pkt_t; + +typedef struct{ + const char *device_name; + const char *pkt_filter; /* ijЩ֧ */ + flwd_cap_mode_t cap_mode; + flwd_topology_t topo_mode; + unsigned int device_ip_net_order; /* 豸IPַ */ + unsigned int device_ip_mask_net_order; /* 豸IP */ + unsigned int gateway_ip_net_order; /* ĬIPַ */ +// unsigned int *device_slave_ip_net_order; /* ˫IPģʽ, , ģʽһ, ͬʱתغͽն˵Ļ, ͬIP */ +// unsigned char device_slave_ip_num; /* ҪDNATĽغʵͨ, ֻһIP, 󲢷ֻ65411, ʹöipַ, ܱ֤߲ */ + unsigned short socket_port_net_order; /* loػػsocketͨŶ˿ģʽ */ + unsigned char local_mac_addr[6]; +}flwd_io_para_t; + +typedef struct __flwd_device_handle{ + int tot_thread_count; + int sapp_send_thread_seq; /* Բʽصsappʱ, ǰ̵߳ķ߳ID */ + flwd_io_para_t io_para; /* , , ģʽ, ӿIP,MACַȵ */ + void *low_level_io_handle; + int (*low_level_io_init)(struct __flwd_device_handle *h); + void (*low_level_io_run)(struct __flwd_device_handle *h); + int (*low_level_pkt_recv)(struct __flwd_device_handle *h, int tid, void **mbuff); + void (*low_level_pkt_free)(struct __flwd_device_handle *h, int tid, void *mbuff); + void *(* low_level_mbuff_malloc)(struct __flwd_device_handle *h, int tid, int len); + void (* low_level_mbuff_free)(struct __flwd_device_handle *h, int tid, void *mbuff); + void (* low_level_mbuff_free_after_send)(struct __flwd_device_handle *h, int tid, void *mbuff); /* marsioģʽͺԶfree, ijЩֲԶfree, ôһӿ */ + void (* low_level_mbuff_send_back)(struct __flwd_device_handle *h, int tid, void *mbuff); /* GDEVģʽ, fwdػעݰ */ + char * (* low_level_mbuff_mtod)(void *mbuff); + char * (*low_level_mbuff_data_append)(void *mbuff, const char *user_data, int user_data_len); + char * (*low_level_mbuff_data_forward)(void *mbuff, int n); /* ָǰƶNֽ, ݳԶN */ + char * (*low_level_mbuff_data_rearward)(void *mbuff, int n); /* ָƶNֽ, ݳԶN */ + int (*low_level_mbuff_get_pkt_len)(void *mbuff); + void (*low_level_mbuff_set_pkt_len)(void *mbuff, int pkt_len); + int (*low_level_send)(struct __flwd_device_handle *h, int tid, void *mbuff); /* ֮ǰlow_level_mbuff_malloc(), Զfree, low_level_mbuff_free() */ +}flwd_device_handle_t; + + +/* Ϊ, ڲΪÿ, maatصtable_idͬ */ +typedef enum{ + FLWD_MAAT_TB_IR_POLICY_COMPILE = 0, + FLWD_MAAT_TB_IR_POLICY_GROUP, + FLWD_MAAT_TB_IR_POLICY_IP, + FLWD_MAAT_TB_IR_STATIC_IP_POOL_CB, /* û˹IP */ + FLWD_MAAT_TB_IR_DYN_SIFT_IP_CB, /* ԶIP */ + FLWD_MAAT_TB_IR_DYN_CONN_IP, /* ɢIPõԪ, ֮ϵͳ, ϵͳڳͻ */ + FLWD_MAAT_TB_MAX, +}flwd_inner_maat_table_id_t; + +typedef struct{ + const char *table_name; + int table_id; +}flwd_maat_table_info_t; + +typedef struct{ + void *flwd_log_handle; /* MESA-handle_logger־ */ + void *maat_log_handle; + void *maat_static_handle; /* redis÷, maatҲҪʼͬ */ + void *maat_dynamic_handle; /* redis÷, maatҲҪʼͬ */ + void *flwd_network_conn_table; /* gdevforward֮Ļϵ */ + void *flwd_arp_table; /* ARP HASH, ipΪkey, mac_addrΪdata */ + pthread_rwlock_t flwd_arp_htable_rwlock; /* arpҪ̬, htableֻл, 󲿷Ƕ, Ҫд, ߶߳ */ + time_t cur_time; + struct in6_addr zero_ipv6_addr; /* ʾȫ0IPv6ַ */ + unsigned char zero_mac_addr[6]; /* ʾȫ0MACַ */ + unsigned long long cur_time_usec; /* 1970-01-01 ʼǰʱľ΢ */ + flwd_device_handle_t global_io_handle[__TOPO_MODE_MAX]; + flwd_maat_table_info_t maat_table_info[FLWD_MAAT_TB_MAX]; +}flwd_global_val_t; /* ȫֱ */ + + +typedef struct{ + unsigned long long eth_pkt_num; + unsigned long long ip_pkt_num; + unsigned long long tcp_pkt_num; + unsigned long long udp_pkt_num; + + unsigned long long eth_pkt_byte; + unsigned long long ip_pkt_byte; + unsigned long long tcp_pkt_byte; + unsigned long long udp_pkt_byte; + +}flwd_pkt_stat_t; /* ݰͳϢ */ + + +/* ԴĿķԵǰΪ׼ */ +struct __flwd_tuple4{ + unsigned char addr_type; /* ѵַͷֹṹǰ, v4, v6ʶ */ + unsigned char protocol; /* TCPUDPԪҪ, Эֶ */ + unsigned short sport_net_order; + unsigned short dport_net_order; + unsigned int sip_net_order; + unsigned int dip_net_order; +}__attribute__((packed)); +typedef struct __flwd_tuple4 flwd_tuple4v4_t; + +/* ԴĿķԵǰΪ׼ */ +struct __flwd_tuple6{ + unsigned char addr_type; /* ѵַͷֹṹǰ, v4, v6ʶ */ + unsigned char protocol; /* TCPUDPԪҪ, Эֶ */ + unsigned short sport_net_order; + unsigned short dport_net_order; + struct in6_addr sip_net_order; + struct in6_addr dip_net_order; +}__attribute__((packed)); +typedef struct __flwd_tuple6 flwd_tuple4v6_t; + + +typedef struct{ + unsigned int gdev_ip_net_order; /* ¼IPGDEV IP, ʵʾDZҵloopback ip, region_id, dev_idͨõ */ + unsigned char region_id; /* ڱ */ + unsigned char dev_id; /* 豸 */ + unsigned char link_id; /* ǰIPʱ· */ + unsigned char this_ip_as_sip_route_dir; /* ˻ԾIPΪԴIPʱ, INLINE豸ķλ, һҪTCPSYNӵ, udpܻύsipdip, ΪΪԴַ, ֵͨ */ + unsigned char inner_raw_smac[6]; + unsigned char inner_raw_dmac[6]; +}flwd_gdev_associated_args_t; + + +/* 洢תеĵײ·Ϣ, ÿζ̬·ɱ, ARP, ÿռ任ʱ!!! + SNAT: + access: + տͻݰ, ¼ͻԴMAC; + ѡĻԾIPλ, ̬ѯһfwd, ¼fwd_ip, fwd_mac; + + fwd: + accessİ, hash, ¼access_ip, access_mac; + յgdevĻظ, ֱȡnat_infoеaccess_ip, access_mac, ֱת(ĴĻȥ). + + DNAT: + fwd: + յgdevװ, ̬ѯdip̨accessؿԵ, ¼access_ip, access_mac; + + access: + յfwdװ, ¼fwd_ip, fwd_mac, յʵӦʱ, ȡ洢ip,macֱת(ĴĻȥ). +*/ +typedef struct{ + flwd_gdev_associated_args_t gdev_args; + unsigned char inner_terminal_mac[6]; /* Ҫaccess_gateway, ͻ˻ʵMAC, SNATӦòARP; DNATװҪѯARPһ */ + unsigned int next_gateway_ip_net; /* Ҫaccess_gatewayfwd_gateway, һصIP, ʵʾvxlanIPַ, v4,v6, ϶IPv4ַ */ + unsigned char next_gateway_mac[6]; /* Ҫaccess_gatewayfwd_gateway, һصMAC */ +}flwd_route_info_t; + + +typedef struct{ + unsigned char tid; /* Ҫhtableصڲtid */ + unsigned char reference; /* ˽ṹhtableбͬkey, ü, ֹdouble free */ + unsigned char act_ip_region; /* flwd_ip_region_type_t, ¼ԾIPڵλ, ӽ, ն˿ʱʹ */ + unsigned char act_ip_origin; /* flwd_active_ip_type_t, ̬ or û */ + flwd_nat_type_t nat_type; + flwd_tuple5_t inner_nat_tuple5; /* SNAT, Ǿڲʵͻ˵İ; */ + flwd_tuple5_t outer_nat_tuple5; /* SNAT, dz, Internetϵİ; */ + signed long long signature_param; /* ݰָЭض, TCP˵, SYN-ISNƫ; DNS˵, transidƫ; ֵafter-natIJתΪ64bit long long ͼȥԭʼpre-nat(64bit)IJ֮ */ + flwd_route_info_t flwd_route_info; +#if FLWD_USE_LTSM_FOR_QUICK_CLOSE + void *ltsm_stat_handle; +#endif +}flwd_nat_info_t; + + +typedef struct{ + unsigned char tid; /* Ҫhtableصڲtid */ + flwd_route_info_t flwd_route_info; +}flwd_fwd_nat_info_t; + + +typedef struct{ + flwd_pkt_stat_t pkt_stat; + /* IPַhtable */ + void *flwd_ip_pool_dynamic_htable[2][2]; /* ʹһά, άȷֱ: [v4_or_v6][inland_or_outland], dynamicstatic洢keyһ, ֿ */ + void *flwd_ip_pool_static_htable[2][2]; /* ʹһά, άȷֱ: [v4_or_v6][inland_or_outland], dynamicstatic洢keyһ, ֿ */ + pthread_rwlock_t flwd_ip_pool_dynamic_rwlock; + pthread_rwlock_t flwd_ip_pool_static_rwlock; + void *nat_info_table; /* accessfwdظͬһ, TCPUDPͬһhtable, protocolҲΪkeyһ */ + flwd_ippair_v6_t nat_key_ipv6_buf; /* 캯ջڵnat_keyʱ, flwd_tuple5_tipv6ַָ, ÿζ̬malloc/free, ˴Ϊÿ̷߳һʱipv6ַ */ + struct stream_tuple4_v4 addrv4_convert_buf; /* flwd_tuple5_to_stream_addr()õڴ滺 */ + struct stream_tuple4_v6 addrv6_convert_buf; /* flwd_tuple5_to_stream_addr()õڴ滺 */ + char __pad[56]; +}flwd_global_thread_t; /* ߳ȫֱ, ע64ֽڻ */ + + + +typedef struct{ + int tot_thread_count; + int flwd_log_level; + int nat_htable_max_num; + int nat_htable_timeout; + int global_access_gateway_num; /* ȫһжٸ, ʹûԾIPԴ˿ */ + int current_access_gateway_id; /* ǰصΨһID, 1ʼ */ + int use_static_pool_ip_if_no_dynamic; /* , ǰûпö̬IP, Ӿ̬ѡһ */ + int use_dynamic_pool_ip_if_no_static; /* , ˲, static_poolǰûпIP, Ӷ̬ѡһ */ + const char *maat_json_cfg_file; + const char* table_info_path; /* maat_cfg */ + const char* full_cfg_dir; /* maat_cfg */ + const char* inc_cfg_dir; /* maat_cfg */ +}flwd_global_cfg_t; /* ȫļ */ + + +typedef struct{ + flwd_topology_t topo_mode; + const char *cfg_file_section; + char addr_para[64]; +}flwd_packet_io_cfg_para_t; + + + +typedef struct { + unsigned char is_valid; + unsigned int policy_group_id; /* ̬IPΪ0 */ + flwd_ip_region_type_t ip_region_type; /* ڡ */ + flwd_active_ip_type_t ip_origin_type; /* ̬, ̬ */ + flwd_ip_t active_ip_net_order; + flwd_gdev_associated_args_t gdev_args; + MESA_list_t active_ip_list_node; /* ̬IPgroup_idΪkey, ͬgroup_idIPʹ; Ϊ˷㴦, quiddityָ򱾽ṹͷ, ʹget_entry_of̫鷳; headͷڵ */ + MESA_list_count_t usable_tcp_sport_list_head; /* TCPö˿, ʼʱ, ȫö˿, һʹƳһ, ӽͷʱ, ٲ, ʹMESA_list_count_t, ڼ */ + MESA_list_count_t usable_udp_sport_list_head; /* UDPö˿, ʼʱ, ȫö˿, һʹƳһ, ӽͷʱ, ٲ, ʹMESA_list_count_t, ڼ */ +}flwd_active_ip_t; + + + +/* ѡԾIPͬʱ, ݵǰIPм¼, ͬʱѡһԴ˿ */ +typedef struct{ + int tid; + flwd_ip_region_type_t dip_region_type; /* ǰԪʵĿIPڵλ */ + flwd_tuple5_t *nat_key; /* ԭʼԪϢ, SNATinner_tuple5, DNATouter_tuple5 */ + flwd_ip_t act_sip_net_order; /* õĻԾIPַ */ + flwd_gdev_associated_args_t gdev_args; + unsigned short act_sport_net_order; + unsigned char protocol; /* ֵhtableصݲ, ʱ */ +}flwd_active_ip_port_args_t; + + + + +/* ΪԾIPMAATص, Ƕڰ߳, Ϊ˲ͬһhtable, ʹһСtrick: + + + op_flagbit: + 0λ: + 0:callback߳Ѿ, ߳̿Զȡ뱾̵߳htable; + 1:߳Ѿ, ʱΪNULL, callback߳̿Լ. + 1λ: + 1:߳ռ; + 0:߳ͷ; + 2λ: + 1:callback߳ռ; + 0:callback߳ͷ; + + 1bit 0bit 0bit + --------|--------|--------| + cb proc valid + + յº, ݿתflwd_active_ip_tƸʽ, ݲͬ߳òͬĶ˿, + Ȼÿ̵߳flwd_temp_active_ip_op_flag=1, +*/ + +//#define FLWD_ACT_IP_OP_MASK_DATA_VALID (0x1) +#define FLWD_ACT_IP_OP_OR_MASK_BY_PROC (0x1) /* ӱλ */ +#define FLWD_ACT_IP_OP_OR_MASK_BY_CALLBACK (0x2) /* ӱλ */ + +#define FLWD_ACT_IP_OP_AND_MASK_BY_PROC (0xFFFE) /* ձλ */ +#define FLWD_ACT_IP_OP_AND_MASK_BY_CALLBACK (0xFFFD) /* ձλ */ + + + +extern flwd_global_cfg_t flwd_cfg_val; +extern flwd_global_val_t flwd_global_val; +extern flwd_global_thread_t flwd_thread_val[FLWD_MAX_THREAD_NUM]; +extern const flwd_packet_io_cfg_para_t g_packet_io_cfg_para[__TOPO_MODE_MAX]; +extern MESA_ATOMIC_T flwd_temp_active_ip_op_flag[FLWD_MAX_THREAD_NUM]; +extern MESA_lqueue_head flwd_temp_active_ip_to_deal[FLWD_MAX_THREAD_NUM]; + +#define flwd_log(level, fmt, args...) do{ if(level >= flwd_cfg_val.flwd_log_level){MESA_handle_runtime_log(flwd_global_val.flwd_log_handle, level, "flowood", fmt, ##args);}}while(0) + +#endif + + diff --git a/inc/flowood_fun.h b/inc/flowood_fun.h new file mode 100644 index 0000000..ec66a73 --- /dev/null +++ b/inc/flowood_fun.h @@ -0,0 +1,92 @@ +#ifndef _FLOWOOD_FUN_H_ +#define _FLOWOOD_FUN_H_ 1 +#include +#include +#include "flowood.h" +#include "flwd_net.h" + +int flwd_gateway_init(void); +int flwd_packet_io_init(flwd_topology_t first_top_mode, flwd_topology_t second_top_mode); +int flwd_access_maat_init(void); +void flwd_packet_io_run(void); +int flwd_access_ip_layer_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt); +int flwd_rubbish_pkt_identify(flwd_device_handle_t *device_handle, flwd_raw_pkt_t *raw_pkt, int check_dip); +void *flwd_stat_thread(void *arg); +int flwd_sendpacket_build_ipv4(u_int16_t carry_layer_len, u_int8_t tos, u_int16_t id, u_int16_t frag, + u_int8_t ttl, u_int8_t prot, u_int32_t src_net_order, u_int32_t dst_net_order, const char *payload, + int payload_s, char *buf); +int flwd_sendpacket_build_ethernet(u_int16_t eth_type_host_order, const unsigned char *src_mac, const unsigned char *dst_mac, char *buf); +int flwd_sendpacket_build_icmpv4_echo(u_int8_t type, u_int8_t code, u_int16_t sum, + u_int16_t id, u_int16_t seq, char *payload, u_int32_t payload_s, char *buf); +int flwd_sendpacket_build_udp(u_int16_t carry_layer_len, + u_int16_t sport_net_order, u_int16_t dport_net_order, + const char *payload, int payload_s, char *buf); + +int flwd_sendpacket_do_checksum(char *ip_buf, int protocol, int len); +int flwd_sendpacket_build_arp(u_short hrd_net, u_short pro_net, u_char hln, u_char pln, u_short op_net, + u_char *sha, u_char *spa, u_char *tha, u_char *tpa, char *buf); +int flwd_packet_io_low_level_init(flwd_device_handle_t *g_io_handle); +void *flwd_packet_io_work_thread(void *arg); +int flwd_access_kernal_pkt_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt); +int flwd_protocol_stack_process(flwd_device_handle_t *io_handle, int tid, flwd_raw_pkt_t *raw_pkt); +int flwd_access_l2tp_layer_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt); +const char *flwd_tuple5_ntop(int tid, const flwd_tuple5_t *tuple5); +const char *flwd_tuple5_ntop_r(const flwd_tuple5_t *tuple5, char *str_mbuf, int mbuf_len); +const char *flwd_ipt_ntop_r(const flwd_ip_t *ipbin, char *str_mbuf, int mbuf_len); +int flwd_idle_call(int tid); +int flwd_access_active_ip_init(void); +flwd_ip_region_type_t flwd_dstip_location(const flwd_tuple5_t *tuple5); +int flwd_pkt_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt); +void *flwd_malloc(int tid, size_t size); +void flwd_free(int tid, void *ptr); +void *flwd_calloc(int tid, size_t nmemb, size_t size); +unsigned int flwd_tuple5_hash(const flwd_tuple5_t *tuple5, int); +flwd_tuple5_t *flwd_tuple5_dup_to_stack(int tid, flwd_tuple5_t *dst_tuple5, const flwd_tuple5_t *src_tuple5); +flwd_tuple5_t *flwd_tuple5_dup_to_heap(flwd_tuple5_t *dst_tuple5, const flwd_tuple5_t *src_tuple5); +void flwd_tuple5_adjust_dir(flwd_tuple5_t *tuple5); +unsigned int compat_marsio_tuple4_hash(const flwd_tuple5_t *nat_key); +int flwd_act_ip_hash_proc(int tid, flwd_active_ip_t *act_ip_stack); +int flwd_nat_htable_key_cmp(const uchar * key1, uint size1, const uchar * key2, uint size2); +uint flwd_nat_htable_key2index(const MESA_htable_handle table, const uchar * key, uint size); +uchar * flwd_nat_htable_key_dup(const uchar *key, uint key_size); +void flwd_nat_htable_key_free(uchar *key, uint key_size); +void flwd_adapt_sleep(int success_work_times_in_recent_100); +int flwd_build_tuple4_key(int tid, flwd_tuple5_t *nat_key, const flwd_raw_pkt_t *raw_pkt); +int flwd_pre_process_pkt_input(flwd_device_handle_t *rcv_device_handle, flwd_raw_pkt_t *raw_pkt); +int flwd_maat_talbe_name_init(void); +int flwd_maat_table_register(void *handle, int inner_table_index); +unsigned int flwd_access_maat_scan_rule(int tid, const flwd_tuple5_t *tuple5); +flwd_active_ip_t *flwd_ip_pool_search(unsigned char act_ip_origin, const MESA_htable_handle table, const uchar * key, uint size); +void flwd_ip_dyn_sift_pool_cb(int table_id,const char* table_line,void* u_para); +void flwd_ip_pool_del(unsigned char act_ip_origin, MESA_htable_handle table, unsigned int policy_group_id, + void (* del_cb)(void *), const flwd_active_ip_t *maat_cb_tobe_del_ip); + +int flwd_maat_talbe_name_init(void); +flwd_ip_region_type_t flwd_ipv4_location(unsigned int ip4addr); +flwd_ip_region_type_t flwd_ipv6_location(const struct in6_addr *ip6addr); +void flwd_act_ip_update(const flwd_active_ip_t *stack_act_ip); +void * flwd_maat_summon(const char *cfg_file, const char *cfg_section); +int flwd_ipt_equal(const flwd_ip_t *ip1, const flwd_ip_t *ip2); + +const char *flwd_ip_region_ntop(int ip_region_type); +int flwd_arp_table_init(void); +int flwd_arp_table_query(int tid, flwd_ip_t *ip_union, flwd_device_handle_t *io_handle, unsigned char result_mac[6]); +void flwd_arp_response_update(const flwd_arp_hdr_t *arp_hdr); +int flwd_tuple5_to_stream_addr(int tid, const flwd_tuple5_t *tuple5, struct ipaddr *stream_addr); +unsigned int flwd_search_fwd_ip_by_gdev_ip(unsigned int active_ip_net_order); +void flwd_del_last_rn(char *data, int max_len); +int flwd_network_conn_init(void); +unsigned char *flwd_policy_group_id_key_gen(unsigned int policy_group_id, unsigned char *out_key, int *out_key_len); +const char *flwd_debug_print_tuple4(const void *a_packet, int tid); +const char *flwd_debug_print_tuple4_r(const void *a_packet, char *buf, int buf_max_len); +const char *flwd_debug_print_tuple4_detail(const void *a_packet, int tid); +const char *flwd_debug_print_tuple4_detail_r(const void *a_packet, char *buf, int buf_max_len); + +unsigned short flwd_act_ip_get_usable_tcp_sport_num(void); +unsigned short flwd_act_ip_get_usable_udp_sport_num(void); + + + + +#endif + diff --git a/inc/flwd_net.h b/inc/flwd_net.h new file mode 100644 index 0000000..2651021 --- /dev/null +++ b/inc/flwd_net.h @@ -0,0 +1,389 @@ +#ifndef _FLWD_NET_H_ +#define _FLWD_NET_H_ 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* һflwdģõͷļ, linux BSDһ */ + +struct flwd_eth_hdr{ + unsigned char h_dest[ETH_ALEN]; /* destination ethernet address */ + unsigned char h_source[ETH_ALEN]; /* source ethernet address */ + unsigned short h_proto; /* packet type ID */ +}__attribute__((packed)); +typedef struct flwd_eth_hdr flwd_eth_hdr_t; + +typedef struct { + u_short ar_hrd; /* format of hardware address */ + + u_short ar_pro; /* format of protocol address */ + u_char ar_hln; /* length of hardware address */ + u_char ar_pln; /* length of protocol addres */ + u_short ar_op; /* operation type */ + + /* + * These should implementation defined but I've hardcoded eth/IP. + */ + u_char ar_sha[6]; /* sender hardware address */ + u_char ar_spa[4]; /* sender protocol address */ + u_char ar_tha[6]; /* target hardware address */ + u_char ar_tpa[4]; /* target protocol address */ +}flwd_arp_hdr_t; + +/* + * Structure of an internet header, naked of options. + */ +typedef struct + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ip_hl:4; /* header length */ + unsigned int ip_v:4; /* version */ +#endif +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int ip_v:4; /* version */ + unsigned int ip_hl:4; /* header length */ +#endif + u_int8_t ip_tos; /* type of service */ + u_short ip_len; /* total length */ + u_short ip_id; /* identification */ + u_short ip_off; /* fragment offset field */ +#define IP_RF 0x8000 /* reserved fragment flag */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u_int8_t ip_ttl; /* time to live */ + u_int8_t ip_p; /* protocol */ + u_short ip_sum; /* checksum */ + struct in_addr ip_src, ip_dst; /* source and dest address */ +}flwd_ipv4_hdr_t; + +/* + * IPv6 packet header prototype, add by LiJia 2012-03-19. + */ +typedef struct{ + u_int8_t ip6_flags[4]; /* version, traffic-class, flow-label */ + u_int16_t ip6_payload_len; /* payload length, not contain header */ + u_int8_t ip6_nxt_hdr; /* next header, same as protocol in IPv4 */ + u_int8_t ip6_hop; /* hop limit, same as TTL in IPv4 */ + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* dest address */ +}flwd_ipv6_hdr_t; + +#define FLWD_IPV4_MULTICAST_ADDR(addr) (((addr&0xF0000000)==0xE0000000)?1:0) + +/* + * ICMP packet header prototype. // from libnet-headers.h + */ +typedef struct +{ + u_char icmp_type; +/* + * ICMP types. + */ +#ifndef ICMP_ECHOREPLY +#define ICMP_ECHOREPLY 0 +#endif +#ifndef ICMP_UNREACH +#define ICMP_UNREACH 3 +#endif +#ifndef ICMP_SOURCEQUENCH +#define ICMP_SOURCEQUENCH 4 +#endif +#ifndef ICMP_REDIRECT +#define ICMP_REDIRECT 5 +#endif +#ifndef ICMP_ECHO +#define ICMP_ECHO 8 +#endif +#ifndef ICMP_ROUTERADVERT +#define ICMP_ROUTERADVERT 9 +#endif +#ifndef ICMP_ROUTERSOLICIT +#define ICMP_ROUTERSOLICIT 10 +#endif +#ifndef ICMP_TIMXCEED +#define ICMP_TIMXCEED 11 +#endif +#ifndef ICMP_PARAMPROB +#define ICMP_PARAMPROB 12 +#endif +#ifndef ICMP_TSTAMP +#define ICMP_TSTAMP 13 +#endif +#ifndef ICMP_TSTAMPREPLY +#define ICMP_TSTAMPREPLY 14 +#endif +#ifndef ICMP_IREQ +#define ICMP_IREQ 15 +#endif +#ifndef ICMP_IREQREPLY +#define ICMP_IREQREPLY 16 +#endif +#ifndef ICMP_MASKREQ +#define ICMP_MASKREQ 17 +#endif +#ifndef ICMP_MASKREPLY +#define ICMP_MASKREPLY 18 +#endif + u_char icmp_code; +/* + * ICMP codes. + */ +#ifndef ICMP_UNREACH_NET +#define ICMP_UNREACH_NET 0 +#endif +#ifndef ICMP_UNREACH_HOST +#define ICMP_UNREACH_HOST 1 +#endif +#ifndef ICMP_UNREACH_PROTOCOL +#define ICMP_UNREACH_PROTOCOL 2 +#endif +#ifndef ICMP_UNREACH_PORT +#define ICMP_UNREACH_PORT 3 +#endif +#ifndef ICMP_UNREACH_NEEDFRAG +#define ICMP_UNREACH_NEEDFRAG 4 +#endif +#ifndef ICMP_UNREACH_SRCFAIL +#define ICMP_UNREACH_SRCFAIL 5 +#endif +#ifndef ICMP_UNREACH_NET_UNKNOWN +#define ICMP_UNREACH_NET_UNKNOWN 6 +#endif +#ifndef ICMP_UNREACH_HOST_UNKNOWN +#define ICMP_UNREACH_HOST_UNKNOWN 7 +#endif +#ifndef ICMP_UNREACH_ISOLATED +#define ICMP_UNREACH_ISOLATED 8 +#endif +#ifndef ICMP_UNREACH_NET_PROHIB +#define ICMP_UNREACH_NET_PROHIB 9 +#endif +#ifndef ICMP_UNREACH_HOST_PROHIB +#define ICMP_UNREACH_HOST_PROHIB 10 +#endif +#ifndef ICMP_UNREACH_TOSNET +#define ICMP_UNREACH_TOSNET 11 +#endif +#ifndef ICMP_UNREACH_TOSHOST +#define ICMP_UNREACH_TOSHOST 12 +#endif +#ifndef ICMP_UNREACH_FILTER_PROHIB +#define ICMP_UNREACH_FILTER_PROHIB 13 +#endif +#ifndef ICMP_UNREACH_HOST_PRECEDENCE +#define ICMP_UNREACH_HOST_PRECEDENCE 14 +#endif +#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF +#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 +#endif +#ifndef ICMP_REDIRECT_NET +#define ICMP_REDIRECT_NET 0 +#endif +#ifndef ICMP_REDIRECT_HOST +#define ICMP_REDIRECT_HOST 1 +#endif +#ifndef ICMP_REDIRECT_TOSNET +#define ICMP_REDIRECT_TOSNET 2 +#endif +#ifndef ICMP_REDIRECT_TOSHOST +#define ICMP_REDIRECT_TOSHOST 3 +#endif +#ifndef ICMP_TIMXCEED_INTRANS +#define ICMP_TIMXCEED_INTRANS 0 +#endif +#ifndef ICMP_TIMXCEED_REASS +#define ICMP_TIMXCEED_REASS 1 +#endif +#ifndef ICMP_PARAMPROB_OPTABSENT +#define ICMP_PARAMPROB_OPTABSENT 1 +#endif + + u_short icmp_sum; + + union + { + struct + { + u_short id; + u_short seq; + }echo; + +#undef icmp_id +#undef icmp_seq +#define icmp_id hun.echo.id +#define icmp_seq hun.echo.seq + + u_long gateway; + struct + { + u_short pad; + u_short mtu; + }frag; + }hun; + union + { + struct + { + n_time its_otime; + n_time its_rtime; + n_time its_ttime; + }ts; + struct + { + struct ip idi_ip; + /* options and then 64 bits of data */ + }ip; + u_long mask; + char data[1]; + +#undef icmp_mask +#define icmp_mask dun.mask +#undef icmp_data +#define icmp_data dun.data + +#undef icmp_otime +#define icmp_otime dun.ts.its_otime +#undef icmp_rtime +#define icmp_rtime dun.ts.its_rtime +#undef icmp_ttime +#define icmp_ttime dun.ts.its_ttime + }dun; + +}flwd_icmp_hdr_t; + +/* 2012-04-10 LiJia add, + ׼ICMPͷڸӣ + ICMPЭͷECHO_REQUESTECHO_REPLAY. +*/ +typedef struct{ + unsigned char icmp_type; + unsigned char icmp_code; + unsigned short icmp_cksum; + unsigned short icd_id; + unsigned short icd_seq; + //char echo_data[......]; +}flwd_simple_icmp_hdr_t; + + +#ifndef TH_FIN +#define TH_FIN 0x01 +#endif + +#ifndef TH_SYN +#define TH_SYN 0x02 +#endif + +#ifndef TH_RST +#define TH_RST 0x04 +#endif + +#ifndef TH_PUSH +#define TH_PUSH 0x08 +#endif + +#ifndef TH_ACK +#define TH_ACK 0x10 +#endif + +#ifndef TH_URG +#define TH_URG 0x20 +#endif + +typedef struct{ + u_int16_t th_sport; /* source port */ + u_int16_t th_dport; /* destination port */ + u_int32_t th_seq; /* sequence number */ + u_int32_t th_ack; /* acknowledgement number */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + u_int8_t th_x2:4, /* (unused) */ + th_off:4; /* data offset */ +#elif __BYTE_ORDER == __BIG_ENDIAN + u_int8_t th_off:4, /* data offset */ + th_x2:4; /* (unused) */ +#else +#error "Please check " +#endif + u_int8_t th_flags; /* control flags */ + u_int16_t th_win; /* window */ + u_int16_t th_sum; /* checksum */ + u_int16_t th_urp; /* urgent pointer */ +}flwd_tcp_hdr_t; + + +/* + * UDP packet header prototype. + */ +typedef struct{ + u_int16_t uh_sport; /* soure port */ + u_int16_t uh_dport; /* destination port */ + u_int16_t uh_ulen; /* length */ + u_int16_t uh_sum; /* checksum */ +}flwd_udp_hdr_t; + + +/* ׼vxlan */ +typedef struct{ + unsigned char flags; + /*------------byte delim -------*/ + unsigned char reserved[3]; + + /*--------int delim -------*/ + unsigned char vlan_id_half_high; + unsigned char link_layer_type : 4; /* 㱨ķװʽ */ + unsigned char vlan_id_half_low : 4; + unsigned int online_test : 1; + unsigned int link_id : 6; + unsigned int dir : 1; + + unsigned int r7 : 1; + unsigned int r6 : 1; + unsigned int r5 : 1; + unsigned int r4 : 1; + unsigned int vni_flag : 1; + unsigned int r2 : 1; + unsigned int r1 : 1; + unsigned int r0 : 1; +}__vxlan_standard_hdr_t; + +/* + ˽ṹ׼vxlan(RFC7348) __vxlan_standard_hdr_t ͬ, ʹijЩԤֶ, + accessforward֮ڲͨѶ, gdev, ijЩֵʹ. +*/ +typedef struct{ + unsigned char flags; + + /*------------byte delim -------*/ + unsigned char reserved[3]; + + /*--------int delim -------*/ + unsigned char vlan_id_half_high; + unsigned char link_layer_type : 4; /* 㱨ķװʽ */ + unsigned char vlan_id_half_low : 4; + unsigned int online_test : 1; + unsigned int link_id : 6; + unsigned int dir : 1; + + unsigned int r7 : 1; + unsigned int r6 : 1; + unsigned int r5 : 1; + unsigned int r4 : 1; + unsigned int vni_flag : 1; + unsigned int r2 : 1; + unsigned int r1 : 1; + unsigned int first_pkt_per_stream : 1; /* ˱, ʾһװ, access֪ͨfwd */ + +}flwd_vxlan_hdr_t; + +#define FLWD_VXLAN_OUTER_PACKET_LEN (sizeof(flwd_eth_hdr_t)+sizeof(flwd_ipv4_hdr_t)+sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t)) +#endif + diff --git a/inc/ltsm.h b/inc/ltsm.h new file mode 100644 index 0000000..340aa2f --- /dev/null +++ b/inc/ltsm.h @@ -0,0 +1,117 @@ +#ifndef __LTSM_H_ +#define __LTSM_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + LTSM : Light TCP State Machine. + Version : 2018-01-16 +*/ + +/* RFC׼TCPЭջ״̬ */ +enum full_tcp_state{ + FTSM_VOID, /* һĵһSYN, شֵ */ + FTSM_SYN_SENT, + FTSM_SYN_RCVD, + FTSM_ESTABLISHED, + FTSM_FIN_WAIT, + FTSM_CLOSE_WAIT, + FTSM_LAST_ACK, + FTSM_TIME_WAIT, + FTSM_CLOSED, + FTSM_LISTEN, + __FTSM_MAX, +}; + +/* + TCP״̬, + ʵֻ״̬:½, , , + ÿض1START1CLOSE״̬, ܰ0ɸDATA״̬. + + VOID״̬ڵ߿жǷҪ. +*/ +enum light_tcp_state{ + LTSM_VOID, /* һĵһSYN, شֵ */ + LTSM_START, + LTSM_DATA, + LTSM_CLOSE, +}; + +struct ltsm_iphdr + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ip_hl:4; /* header length */ + unsigned int ip_v:4; /* version */ +#endif +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int ip_v:4; /* version */ + unsigned int ip_hl:4; /* header length */ +#endif + u_int8_t ip_tos; /* type of service */ + u_short ip_len; /* total length */ + u_short ip_id; /* identification */ + u_short ip_off; /* fragment offset field */ +#define IP_RF 0x8000 /* reserved fragment flag */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u_int8_t ip_ttl; /* time to live */ + u_int8_t ip_p; /* protocol */ + u_short ip_sum; /* checksum */ + struct in_addr ip_src, ip_dst; /* source and dest address */ + }; + +struct ltsm_tcphdr + { + u_int16_t th_sport; /* source port */ + u_int16_t th_dport; /* destination port */ + u_int32_t th_seq; /* sequence number */ + u_int32_t th_ack; /* acknowledgement number */ +# if __BYTE_ORDER == __LITTLE_ENDIAN + u_int8_t th_x2:4; /* (unused) */ + u_int8_t th_off:4; /* data offset */ +# endif +# if __BYTE_ORDER == __BIG_ENDIAN + u_int8_t th_off:4; /* data offset */ + u_int8_t th_x2:4; /* (unused) */ +# endif + u_int8_t th_flags; +# define TH_FIN 0x01 +# define TH_SYN 0x02 +# define TH_RST 0x04 +# define TH_PUSH 0x08 +# define TH_ACK 0x10 +# define TH_URG 0x20 + u_int16_t th_win; /* window */ + u_int16_t th_sum; /* checksum */ + u_int16_t th_urp; /* urgent pointer */ +}; + +struct ltsm_result{ + enum full_tcp_state fstate; + enum light_tcp_state lstate; +}; + +typedef void * ltsm_stream_handle; + +ltsm_stream_handle ltsm_create_handle(void); + +#define LTSM_DIR_C2S 0 +#define LTSM_DIR_S2C 1 + +struct ltsm_result ltsm_get_current_state(ltsm_stream_handle pltsm, uint8_t tcp_flags, uint8_t dir); + +const char *ltsm_fstate_ntop(enum full_tcp_state fstate); +const char *ltsm_lstate_ntop(enum light_tcp_state lstate); + +void ltsm_destroy_handle(ltsm_stream_handle pltsm); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/lib/libltsm.a b/lib/libltsm.a new file mode 100644 index 0000000..93538db Binary files /dev/null and b/lib/libltsm.a differ diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..c244e92 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,59 @@ +#CC=gcc +CC=g++ +CCC=g++ + +ifeq ($(type), $(TYPE_ACCESS)) +TARGET=flowood_access +else +TARGET=flowood_forward.so +endif + +CFLAGS += -g -fPIC -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 -ldl -lMESA_handle_logger -lMESA_htable -lMESA_prof_load + +COMMON_OBJS=flowood_main.o common/flwd_common_stack.o common/flwd_sendpacket.o common/flwd_status.o +COMMON_OBJS += common/flwd_common_tool.o +COMMON_OBJS += common/flwd_compat_marsio_hash.o +COMMON_OBJS += common/linux_jhash_algo.o +COMMON_OBJS += common/flwd_arp.o +COMMON_OBJS += common/flwd_common_hash.o +COMMON_OBJS += packet_io/flwd_packet_io.o + +ACC_OBJS = access/flowood_access.o +ACC_OBJS += access/flwd_access_ip_layer.o +ACC_OBJS += access/flwd_access_active_ip_manage.o +ACC_OBJS += access/flwd_access_idle_call.o +ACC_OBJS += access/flwd_access_maat.o +ACC_OBJS += common/flwd_common_maat.o +ACC_OBJS += common/flwd_network_connect.o +ACC_OBJS += ../lib/libltsm.a + +FWD_OBJS = forward/flowood_forward.o +FWD_OBJS += forward/flwd_fwd_idle_call.o + +all:$(TARGET) + +.c.o: + $(CCC) -c $(CFLAGS) -I. $(H_DIR) $< + +.cpp.o: + $(CCC) -c $(CFLAGS) -I. $(H_DIR) $< + +flowood_access: $(COMMON_OBJS) $(ACC_OBJS) + (rm -f $@; $(CC) -o $@ -Wl,--export-dynamic $(CFLAGS) $^ $(LIB) -lmaatframe ; cp $@ ../bin;) + +#flowood_forward: $(COMMON_OBJS) $(FWD_OBJS) + #(rm -f $@; $(CC) -o $@ -Wl,--export-dynamic $(CFLAGS) $^ $(LIB); cp $@ ../bin;) + +flowood_forward.so: $(COMMON_OBJS) $(FWD_OBJS) + (rm -f $@; $(CC) -o $@ -shared $(CFLAGS) $^ $(LIB); cp $@ /opt/MESA/lib) + + +clean: + rm -f *.o access/*.o common/*.o packet_io/*.o forward/*.o $(TARGET) 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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* + 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_pooldynamic_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: + ֹ, ǶԳ·, S2CC2Sͬһ̨ת, + + Ҫӱɢȫת, + + Ԫ, dip+dport+sip, Ԫ̫, + + sportһָ㷨, ɨԪжsport. +*/ +static int flwd_link_table_broadcast(int tid, flwd_nat_info_t *nat_info) +{ + /* TODO: + ֹ, ǶԳ·, S2CC2Sͬһ̨ת, + + Ҫӱɢȫת. + */ + 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, dportDzܱ, sipҲѡܱ, ֻԴ˿һЩtrick, + Ҷ֮ͬ, صIJ֮ͬ߳ѾԤȷ˶˿ڷΧ, + һԾIP˵, ˿trickķΧС, ׼ȷȺܵ! + + ȡһ²: + 1,TCPЭ, ʹSYN-ISNת, ͨ32bitISNhash, Ϊָ; + 2,DNSЭ, ʹDNS-TRANSIDת, ͨ16bitTRANSIDΪָ, ͻʱ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) +{ + /* + תк, ὫSNATDNATʹ洢vxlanijֶΣ + + SNAT, C2SĴ洢NATԪ, S2CĻ, ٴβhtableͬkey ָ֮ǰʵͻIPPORT; + + DNAT, һSYNɨIPòԱ, ҵһõRIPRPORT, ȻҲ洢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ģʽҪvxlanethernet */ + 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; + } + } + + /* ݻԾIPIJʱgdevIP, ѯGDEVMAC, 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ص, vxlansport */ + 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, + յipacc-userһĴ. + + : + acc-userֻһio_handle, Ŀǰpcap, marsio, socket, tap, + pcaptapľԲһ, + + ʽ: + 1, һFlowood_IO(ĸ, acc-user, acc-fwd, fwd-acc, fwd-gdev), ɶӦIO, + acc-userIOIO, ͬĽ뷽ʽ: 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, + + ACCUSERתʱ, ͨ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, snatouter->tuple5sip, ʵԴIP; + dnatûжԴ, ֻǼ򵥵Ľvirtual_dip:virtual_dportijreal_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: ȡö˿ʱֳfreeMESA_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, ҵͬһhtabledata, 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: ʧ, ˴Ҫʹinnerkey, Ϊ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, innerouterһ, keyĴ洢λ, sip,dipĴСϵܲһ */ + unsigned int outer_actual_dport_net_order; /* ͻȥʵĿ˿, innerouterһ, 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)); /* snatinner 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{ + /* innerouterIPַͬ, 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, innerouterһ, keyĴ洢λ, sip,dipĴСϵܲһ */ + unsigned int outer_actual_dport_net_order; /* ͻȥʵĿ˿, innerouterһ, 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)); /* snatinner 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{ + /* innerouterIPַͬ, 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; +} + +/* + accessuserհ, 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 +#include +#include +#include +#include +#include +#include +#include + + +/* + 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, ߳id0ʼ, 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, ߳id0ʼ, 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, Ϊkeyhtable, + ݵǰص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ͺͽһIPstatic˵, ¹һڵ, quiddityִṹͷ */ + + /* TCPUDPĶ˿ڷֿ洢ʹ, չһԾ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; +} + + +/* ̬IPgroup_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_idip_list, Ȼٱ; ö˿ڻʱ, ֻIPͶ˿, ûGroup_idĸ, + flwd_ip_pool_static_htable, ʹͬkey, ͬһdata, ip_list. + + update_cbʹgroup_idip_list; + sport_recycleʹipַip_list; + + Ϊ˷ֹһgroup_idipv4ַͻ, groupתΪַģʽ, ǰGPIDǰ׺, ֤keyijȶһ, ϶Ҳͻ. + */ + 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: + ̬ԾIPIPַΪkey, dataΪflwd_active_ip_t, ֻһڵ, active_ip_list_nodeָ붼ǿ; + ̬IPַصĵַԲIDΪkey, dataΪflwd_active_ip_t, ͬpolicy_idIP; +*/ +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_ipIPϵͳشIP, ; + DNAT˵, act_ipǽip, Ϊֻһip65535˿ڿ, ļ⶯̬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, + ҪЩIParp, ظӦ. +*/ + + +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 +#include +#include +#include +#include +#include +#include + +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 +#include +#include +#include +#include +#include +#include + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static unsigned int flwd_fetch_policy_id_from_user_region(struct Maat_rule_t *maat_res) +{ + char *policy_section; + + /* , 洢Զ, ǰԵIPַص */ + policy_section = strcasestr(maat_res->service_defined, "IR_STRATEGY="); + if(NULL == policy_section){ + return 0; + } + + policy_section += strlen("IR_STRATEGY="); + + return (unsigned int)atoi(policy_section); +} + + +/* + ݵǰͻ˵ԴIP, PORT, ɨĸò: policy_id. + return value: + > 0: success, policy id. + 0: not hit rule; +*/ +unsigned int flwd_access_maat_scan_rule(int tid, const flwd_tuple5_t *tuple5) +{ + int ret; + struct Maat_rule_t maat_res[1]; /* ̫ܶ, Ƕ, ҲֻҪһ, ˴resΪ1 */ + struct ipaddr client_addr; + scan_status_t mid = NULL; + unsigned int hit_policy_id; + + memset(&maat_res[0], 0, sizeof(maat_res)); + + flwd_tuple5_to_stream_addr(tid, tuple5, &client_addr); + + ret = Maat_scan_addr(flwd_global_val.maat_static_handle, + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_POLICY_IP].table_id, /* TODO, SNATDNATԷֿ, 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}; /* ԾIPSMAC */ + 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.1GDEVIP. +*/ +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ʾԴIP1ʾĿIP2ʾ˫ */ + 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ʾԴIP1ʾĿIP2ʾ˫ */ + 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; +} + diff --git a/src/common/Makefile b/src/common/Makefile new file mode 100644 index 0000000..ebc5d73 --- /dev/null +++ b/src/common/Makefile @@ -0,0 +1,42 @@ +#CC=gcc +CC=g++ +CCC=g++ + +TARGET=flwd_common_stack.o flwd_sendpacket.o flwd_status.o flwd_common_tool.o linux_jhash_algo.o +TARGET += flwd_compat_marsio_hash.o +TARGET += flwd_arp.o +TARGET += flwd_common_hash.o +TARGET += flwd_common_maat.o +TARGET += flwd_network_connect.o + + +CFLAGS +=-g -Wall -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) + +flwd_common_hash.o:flwd_common_hash.c + $(CC) -c -O3 $(CFLAGS) -O3 -I. $(H_DIR) $< + +linux_jhash_algo.o:linux_jhash_algo.c + $(CC) -c -O3 $(CFLAGS) -O3 -I. $(H_DIR) $< + +flwd_common_stack.o:flwd_common_stack.c + $(CC) -c -O3 $(CFLAGS) -O3 -I. $(H_DIR) $< + + +.c.o: + $(CC) -c $(CFLAGS) -I. $(H_DIR) $< + +.cpp.o: + $(CCC) -c $(CFLAGS) -I. $(H_DIR) $< + +clean: + rm -f *.o diff --git a/src/common/flwd_arp.c b/src/common/flwd_arp.c new file mode 100644 index 0000000..b593f09 --- /dev/null +++ b/src/common/flwd_arp.c @@ -0,0 +1,252 @@ +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + SNAT, װ϶ǿͻ˷, accessؼ¼¿ͻ˵mac, ÿηѯARP, ÿռ任ʱ. + + DNAT, װⲿ, ڲ, ĿMACû, ҪARPѯ, + ARP첽ģʽ, һβѯ϶û, Ȱѵǰ, õARPӦ, 洢nat_info, İͲٲ. +*/ + +static const unsigned char G_BROADCAST_MAC_ADDR[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; /* 㲥MAC */ + +static void flwd_arp_query_ipv4(int tid, unsigned int dip_net, flwd_device_handle_t *io_handle) +{ + int ret; + void *send_mbuff = io_handle->low_level_mbuff_malloc(io_handle, tid, sizeof(flwd_eth_hdr_t) + sizeof(flwd_arp_hdr_t)); + char *unsend_data_ptr = io_handle->low_level_mbuff_mtod(send_mbuff); + + flwd_eth_hdr_t *ehdr = (flwd_eth_hdr_t *)unsend_data_ptr; + + memcpy(ehdr->h_source, io_handle->io_para.local_mac_addr, ETH_ALEN); + memcpy(ehdr->h_dest, G_BROADCAST_MAC_ADDR, ETH_ALEN); + ehdr->h_proto = htons(ETH_P_ARP); + + flwd_arp_hdr_t *arphdr = (flwd_arp_hdr_t *)(unsend_data_ptr + sizeof(flwd_eth_hdr_t)); + + arphdr->ar_hrd = htons(ARPHRD_ETHER); + arphdr->ar_pro = htons(ETH_P_IP); + arphdr->ar_hln = ETH_ALEN; + arphdr->ar_pln = sizeof(int); + arphdr->ar_op = htons(ARPOP_REQUEST); + + memcpy(arphdr->ar_sha, io_handle->io_para.local_mac_addr, ETH_ALEN); + memcpy(arphdr->ar_spa, &io_handle->io_para.device_ip_net_order, sizeof(int)); + memset(arphdr->ar_tha, 0, ETH_ALEN); + memcpy(arphdr->ar_tpa, &dip_net, sizeof(int)); + + io_handle->low_level_mbuff_set_pkt_len(send_mbuff, sizeof(flwd_eth_hdr_t) + sizeof(flwd_arp_hdr_t)); + + ret = io_handle->low_level_send(io_handle, tid, send_mbuff); + if(ret < 0){ + flwd_log(30, "send arp query packet error! ret = %d.\n", ret); + }else{ + char ip_str[16]; + inet_ntop(AF_INET, &dip_net, ip_str, 16); + flwd_log(10, "send arp query dip:%s.\n", ip_str); + } +} + + +static void flwd_arp_net_query(int tid, const flwd_ip_t *dip_union, flwd_device_handle_t *io_handle) +{ + if(FLWD_IP_ADDR_TYPE_V4 == dip_union->addr_type){ + flwd_arp_query_ipv4(tid, dip_union->addr_ipv4, io_handle); + }else{ + /* TODO, IPv6 <---> ARP, IPv6ھӷЭ */ + assert(0); + } + +} + +/* + ݵǰݰʵĿIP, ͱصַ, + ж϶ethernetMACַ, ӦʹĸIP? +*/ +static unsigned int flwd_judge_layer2_dipv4(unsigned int real_target_ip_net, flwd_device_handle_t *io_handle) +{ + unsigned int real_target_ip_host = ntohl(real_target_ip_net); + unsigned int local_ip_mask_host = ntohl(io_handle->io_para.device_ip_mask_net_order); + unsigned int local_ip_host = ntohl(io_handle->io_para.device_ip_net_order); + + if((real_target_ip_host & local_ip_mask_host) == (local_ip_host & local_ip_mask_host)){ + /* ĿIPͬһ, ֱʹĿIP, ѯARP */ + return real_target_ip_net; + } + + /* ĿIPͬһ, ҪԽ豸, ʹصIPѯARP */ + return io_handle->io_para.gateway_ip_net_order; +} + + +static struct in6_addr * flwd_judge_layer2_dipv6(struct in6_addr *real_target_ip_net, + flwd_device_handle_t *io_handle) +{ + /* TODO, IPv6 */ + return real_target_ip_net; +} + +int flwd_arp_table_query(int tid, flwd_ip_t *target_ip, + flwd_device_handle_t *io_handle, unsigned char result_mac[6]) +{ + unsigned char *res; + +#if FLWD_NO_ACTIVE_ARP_QUERY + /* 172.16.1.201, 10.0.6.201 */ + static unsigned char acc_to_fwd_gateway_mac[6] = {0x74, 0x86,0x7a,0xd0,0x12,0xfc}; + + /* 172.16.1.229, 10.0.6.229 */ + static unsigned char fwd_to_acc_gateway_mac[6] = {0x74, 0x86, 0x7A, 0xD0, 0x1B, 0x30}; + + if(0xC90110AC == target_ip->addr_ipv4){ + memcpy(result_mac, acc_to_fwd_gateway_mac, 6); + return 0; + }else if(0xE50110AC == target_ip->addr_ipv4){ + memcpy(result_mac, fwd_to_acc_gateway_mac, 6); + return 0; + }else{ + abort(); + } +#else + unsigned char *hkey; + unsigned int hkey_size; + unsigned int local_net_dipv4; + + if(FLWD_IP_ADDR_TYPE_V4 == target_ip->addr_type){ + local_net_dipv4 = flwd_judge_layer2_dipv4(target_ip->addr_ipv4, io_handle); + hkey = (unsigned char *)&local_net_dipv4; + hkey_size = sizeof(int); + + target_ip->addr_ipv4 = local_net_dipv4; + }else{ + struct in6_addr *local_net_dip6 = flwd_judge_layer2_dipv6(&target_ip->addr_ipv6, io_handle); + hkey = (unsigned char *)local_net_dip6; + hkey_size = sizeof(struct in6_addr); + } + + pthread_rwlock_rdlock(&flwd_global_val.flwd_arp_htable_rwlock); + res = (unsigned char *)MESA_htable_search(flwd_global_val.flwd_arp_table, hkey, hkey_size); + if(res != NULL){ + memcpy(result_mac, res, 6); /* , Ƚ鵽Ľ, ̾ͱ̸߳, ߳ʱ̭! */ + } + pthread_rwlock_unlock(&flwd_global_val.flwd_arp_htable_rwlock); + + if(NULL == res){ + flwd_arp_net_query(tid, target_ip, io_handle); /* 鲻, Ŀ귢һβѯ */ + return -1; + } +#endif + + return 0; +} + +void flwd_arp_response_update(const flwd_arp_hdr_t *arp_hdr) +{ + unsigned char *res_mac = (unsigned char *)malloc(ETH_ALEN); + int ret; + + memcpy(res_mac, arp_hdr->ar_sha, ETH_ALEN); + + pthread_rwlock_wrlock(&flwd_global_val.flwd_arp_htable_rwlock); + ret = MESA_htable_add(flwd_global_val.flwd_arp_table, arp_hdr->ar_spa, sizeof(int), res_mac); + pthread_rwlock_unlock(&flwd_global_val.flwd_arp_htable_rwlock); + + if(ret < 0){ + free(res_mac); + } +} + +static int flwd_arp_htable_key_cmp(const uchar * key1, uint size1, const uchar * key2, uint size2) +{ + if(size1 != size2){ + return (int)size1 - (int)size2; + } + + return memcmp(key1, key2, size1); +} + + +static uint flwd_arp_htable_key2index(const MESA_htable_handle table, const uchar * key, uint size) +{ + uint i; + uint seed = 13131; // 31 131 1313 13131 131313 etc.. + uint hash = 31; + + for(i = 0; i < size; i++){ + hash = hash * seed + (*key++); + } + + return hash; +} + +static void flwd_arp_htable_data_free(void *data) +{ + free(data); +} + +int flwd_arp_table_init(void) +{ + int opt_int; + + MESA_htable_handle htable = MESA_htable_born(); + + opt_int = 0; /* ⲿʹöд, htableģʽ */ + MESA_htable_set_opt(htable, MHO_THREAD_SAFE, &opt_int, sizeof(int)); + + opt_int = 1024; + MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, &opt_int, sizeof(int)); + + opt_int = 10000; + MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, &opt_int, sizeof(int)); + + opt_int = 120; + MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, &opt_int, sizeof(int)); + + opt_int = HASH_ELIMINATE_ALGO_FIFO; + MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, &opt_int, sizeof(int)); + + MESA_htable_set_opt(htable, MHO_CBFUN_KEY_COMPARE, (void *)&flwd_arp_htable_key_cmp, sizeof(void *)); + + MESA_htable_set_opt(htable, MHO_CBFUN_KEY_TO_INDEX, (void *)&flwd_arp_htable_key2index, sizeof(void *)); + + MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, (void *)&flwd_arp_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 *)"./log/flwd_arp_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); + + flwd_global_val.flwd_arp_table = htable; + + pthread_rwlock_init(&flwd_global_val.flwd_arp_htable_rwlock, NULL); + + return 0; +} + diff --git a/src/common/flwd_common_hash.c b/src/common/flwd_common_hash.c new file mode 100644 index 0000000..563c111 --- /dev/null +++ b/src/common/flwd_common_hash.c @@ -0,0 +1,98 @@ +#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 +#include +#include +#include +#include +#include +#include +#include +#include + +uchar * flwd_nat_htable_key_dup(const uchar *key, uint key_size) +{ + const flwd_tuple5_t *stack_tuple5 = (flwd_tuple5_t *)key; + flwd_tuple5_t *heap_tuple5 = (flwd_tuple5_t *)malloc(sizeof(flwd_tuple5_t)); + + memcpy(heap_tuple5, stack_tuple5, sizeof(flwd_tuple5_t)); + + if(FLWD_IP_ADDR_TYPE_V6 == stack_tuple5->addr_type){ + /* v6, Ҫmallo, memcpyIPַ, עfree!! */ + heap_tuple5->ippair_v6 = (flwd_ippair_v6_t *)malloc(sizeof(flwd_ippair_v6_t)); + memcpy(&heap_tuple5->ippair_v6->sip_net_order, &stack_tuple5->ippair_v6->sip_net_order, sizeof(struct in6_addr)); + memcpy(&heap_tuple5->ippair_v6->dip_net_order, &stack_tuple5->ippair_v6->dip_net_order, sizeof(struct in6_addr)); + } + + return (uchar *)heap_tuple5; +} + +void flwd_nat_htable_key_free(uchar *key, uint key_size) +{ + flwd_tuple5_t *raw_tuple5 = (flwd_tuple5_t *)key; + + if(FLWD_IP_ADDR_TYPE_V6 == raw_tuple5->addr_type){ + free(raw_tuple5->ippair_v6); + } + + free(key); + + return; +} + +uint flwd_nat_htable_key2index(const MESA_htable_handle table, const uchar * key, uint size) +{ + const flwd_tuple5_t *tuple5 = (flwd_tuple5_t *)key; + + return flwd_tuple5_hash(tuple5, 0); +} + + +int flwd_nat_htable_key_cmp(const uchar * key1, uint size1, const uchar * key2, uint size2) +{ + const flwd_tuple5_t *tp1; + const flwd_tuple5_t *tp2; + + tp1 = (flwd_tuple5_t *)key1; + tp2 = (flwd_tuple5_t *)key2; + + if(tp1->addr_type != tp2->addr_type){ + return -1; + } + + if(tp1->protocol != tp2->protocol){ + return -1; + } + + if(tp1->sport_net_order != tp2->sport_net_order){ + return -1; + } + + if(tp1->dport_net_order != tp2->dport_net_order){ + return -1; + } + + if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == tp1->addr_type)){ + if(tp1->ippair_v4.sip_net_order != tp2->ippair_v4.sip_net_order){ + return -1; + } + if(tp1->ippair_v4.dip_net_order != tp2->ippair_v4.dip_net_order){ + return -1; + } + }else{ + if(memcmp(&tp1->ippair_v6->sip_net_order, &tp2->ippair_v6->sip_net_order, sizeof(struct in6_addr))){ + return -1; + } + if(memcmp(&tp1->ippair_v6->dip_net_order, &tp2->ippair_v6->dip_net_order, sizeof(struct in6_addr))){ + return -1; + } + } + + return 0; +} + diff --git a/src/common/flwd_common_maat.c b/src/common/flwd_common_maat.c new file mode 100644 index 0000000..b18671c --- /dev/null +++ b/src/common/flwd_common_maat.c @@ -0,0 +1,153 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_handle_logger.h" +#include "MESA_htable.h" +#include "Maat_rule.h" +#include +#include +#include +#include +#include +#include +#include + + +void * flwd_maat_summon(const char *cfg_file, const char *cfg_section) +{ + char cfg_ip[32]; + char str_tmp[256]; + int ret, tmp_int; + int maat_cfg_src_type; + unsigned short redis_port; + void *maat_handle; + + MESA_load_profile_string_def(FLWD_CONFIG_FILE, cfg_section, "table_info", str_tmp, 256, "$"); + if('$' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "conf->table_info invalid!"); + return NULL; + } + flwd_cfg_val.table_info_path = strdup(str_tmp); + + MESA_load_profile_int_def(cfg_file, cfg_section, "maat_cfg_source", &maat_cfg_src_type, FLWD_MAAT_SRC_JSON); + + if(FLWD_MAAT_SRC_LOCAL_FILE == maat_cfg_src_type){ + MESA_load_profile_string_def(cfg_file, cfg_section, "inc_dir", str_tmp, 256, "$"); + if('$' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "conf->inc_dir invalid!"); + return NULL; + } + flwd_cfg_val.inc_cfg_dir = strdup(str_tmp); + + MESA_load_profile_string_def(cfg_file, cfg_section, "full_dir", str_tmp, 256, "$"); + if('$' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "conf->full_dir invalid!"); + return NULL; + } + flwd_cfg_val.full_cfg_dir = strdup(str_tmp); + + maat_handle = Maat_summon_feather( + FLWD_MAX_THREAD_NUM, + flwd_cfg_val.table_info_path, + flwd_cfg_val.full_cfg_dir, + flwd_cfg_val.inc_cfg_dir, + flwd_global_val.maat_log_handle); + + }else if(FLWD_MAAT_SRC_JSON == maat_cfg_src_type){ + MESA_load_profile_string_def(FLWD_CONFIG_FILE, cfg_section, "json_cfg_file", str_tmp, 256, "$"); + if('$' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "conf->json_cfg_file invalid!"); + return NULL; + } + flwd_cfg_val.maat_json_cfg_file = strdup(str_tmp); + + maat_handle = Maat_summon_feather_json( + FLWD_MAX_THREAD_NUM, + flwd_cfg_val.table_info_path, + flwd_cfg_val.maat_json_cfg_file, + flwd_global_val.maat_log_handle); + }else if(FLWD_MAAT_SRC_REDIS == maat_cfg_src_type){ + MESA_load_profile_string_def(cfg_file, cfg_section, "redis_server_ip", cfg_ip, 32, "$"); + if('$' == cfg_ip[0]){ + flwd_log(30, "Invalid config 'redis_server_ip'!\n"); + exit(1); + } + MESA_load_profile_int_def(cfg_file, cfg_section, "redis_server_port", &tmp_int, 0); + if(tmp_int <= 0 || tmp_int > 65535){ + flwd_log(30, "Invalid config 'redis_server_port'!\n"); + exit(1); + } + redis_port = (unsigned short)tmp_int; + + maat_handle = Maat_feather(FLWD_MAX_THREAD_NUM, flwd_cfg_val.table_info_path, flwd_global_val.maat_log_handle); + tmp_int = 1000; + Maat_set_feather_opt(maat_handle, MAAT_OPT_EFFECT_INVERVAL_MS, &tmp_int, sizeof(int)); + Maat_set_feather_opt(maat_handle, MAAT_OPT_STAT_ON, NULL, 0); + Maat_set_feather_opt(maat_handle, MAAT_OPT_STAT_FILE_PATH, "./log/maat_stat.log", strlen("./log/maat_stat.log") + 2); + ret = Maat_set_feather_opt(maat_handle, MAAT_OPT_REDIS_IP, cfg_ip, strlen(cfg_ip) + 2); + if(ret < 0){ + flwd_log(30, "Maat_set_feather_opt 'MAAT_OPT_REDIS_IP' error, value: %s!\n", cfg_ip); + exit(1); + } + ret = Maat_set_feather_opt(maat_handle, MAAT_OPT_REDIS_PORT, &redis_port, sizeof(short)); + if(ret < 0){ + flwd_log(30, "Maat_set_feather_opt 'MAAT_OPT_REDIS_PORT' error, value: %u!\n", redis_port); + exit(1); + } + + MESA_load_profile_int_def(cfg_file, cfg_section, "redis_index", &tmp_int, -1); + if(-1 == tmp_int){ + flwd_log(30, "Invalid config 'redis_index'!\n"); + exit(1); + } + + ret = Maat_set_feather_opt(maat_handle, MAAT_OPT_REDIS_INDEX, &tmp_int, sizeof(int)); + if(ret < 0){ + flwd_log(30, "Maat_set_feather_opt 'MAAT_OPT_REDIS_INDEX' error, value: %d!\n", tmp_int); + exit(1); + } + + Maat_initiate_feather(maat_handle); + }else{ + flwd_log(30, "Invalid config 'maat_cfg_source'! [1:json; 2:file; 3:redis]\n"); + exit(1); + } + + if(NULL == maat_handle){ + flwd_log(30, "maat init error!\n"); + return NULL; + } + + + + return maat_handle; +} + + +int flwd_maat_table_register(void *maat_handle, int inner_table_index) +{ + assert(inner_table_index < FLWD_MAAT_TB_MAX); + flwd_global_val.maat_table_info[inner_table_index].table_id = + Maat_table_register(maat_handle, flwd_global_val.maat_table_info[inner_table_index].table_name); + + assert(flwd_global_val.maat_table_info[inner_table_index].table_id >= 0); + return flwd_global_val.maat_table_info[inner_table_index].table_id; +} + +/* + NOTE: + Щƶĵ涨, , ʱд. +*/ +int flwd_maat_talbe_name_init(void) +{ + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_POLICY_COMPILE].table_name = strdup("IR_POLICY_COMPILE"); + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_POLICY_GROUP].table_name = strdup("IR_POLICY_GROUP"); + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_POLICY_IP].table_name = strdup("IR_POLICY_IP"); + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_STATIC_IP_POOL_CB].table_name = strdup("IR_STATIC_IP_POOL_CB"); + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_DYN_SIFT_IP_CB].table_name = strdup("IR_DYN_SIFT_IP_CB"); + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_DYN_CONN_IP].table_name = strdup("IR_DYN_CONN_IP"); + + return 0; +} + + diff --git a/src/common/flwd_common_stack.c b/src/common/flwd_common_stack.c new file mode 100644 index 0000000..9dfc09b --- /dev/null +++ b/src/common/flwd_common_stack.c @@ -0,0 +1,449 @@ +/* + ͨЭջģ, ARP, ICMPЭĴ. +*/ + +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_handle_logger.h" +#include +#include +#include +#include +#include +#include +#include +#include + +const unsigned char G_FLWD_BROADCAST_ADDR[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + +/* + TODO: + ӿIPĬ·, ʵIPЭջ, + Ŀܲһ(·VLAN), + Ҫarpһ. +*/ + + +static inline int sendpacket_in_cksum(u_int16_t *addr, int len) +{ + int sum; + int nleft; + u_int16_t ans; + u_int16_t *w; + + sum = 0; + ans = 0; + nleft = len; + w = addr; + + while (nleft > 1) + { + sum += *w++; + nleft -= 2; + } + if (nleft == 1) + { + *(char *)(&ans) = *(char *)w; + sum += ans; + } + return (sum); +} + +/* + * Checksum stuff + */ +#define SENDPACKET_CKSUM_CARRY(x) \ + (x = (x >> 16) + (x & 0xffff), (~(x + (x >> 16)) & 0xffff)) + +int flwd_sendpacket_do_checksum(char *buf, int protocol, int len) +{ + flwd_ipv4_hdr_t *iph_p; + flwd_ipv6_hdr_t *ip6h_p; + int ip_hl; + int sum; + int is_ipv6 = 0; + + sum = 0; + iph_p = (flwd_ipv4_hdr_t *)buf; + + if(4 == iph_p->ip_v) /* IP汾ֶΣIPv4IPv6ʽͬ */ + { + ip_hl = iph_p->ip_hl << 2; + ip6h_p = NULL; + } + else if(6 == iph_p->ip_v) + { + ip6h_p = (flwd_ipv6_hdr_t *)buf; + iph_p = NULL; + ip_hl = sizeof(flwd_ipv6_hdr_t); + is_ipv6 = 1; + } + else + { + return (-1); + } + + /* + * Dug Song came up with this very cool checksuming implementation + * eliminating the need for explicit psuedoheader use. Check it out. + */ + switch (protocol) + { + /* + * Style note: normally I don't advocate declaring variables inside + * blocks of control, but it makes good sense here. -- MDS + */ + case IPPROTO_TCP: + { + flwd_tcp_hdr_t *tcph_p = + (flwd_tcp_hdr_t *)(buf + ip_hl); + +#if (STUPID_SOLARIS_CHECKSUM_BUG) + tcph_p->th_sum = tcph_p->th_off << 2; + return (1); +#endif /* STUPID_SOLARIS_CHECKSUM_BUG */ + + tcph_p->th_sum = 0; + /* 2012-03-19 LiJia add, for IPv6 */ + if(is_ipv6) + { + sum = sendpacket_in_cksum((u_int16_t *)&ip6h_p->ip6_src, 32); + } + else + { + sum = sendpacket_in_cksum((u_int16_t *)&iph_p->ip_src, 8); + } + sum += ntohs(IPPROTO_TCP + len); + sum += sendpacket_in_cksum((u_int16_t *)tcph_p, len); + tcph_p->th_sum = SENDPACKET_CKSUM_CARRY(sum); + break; + } + + case IPPROTO_UDP: + { + flwd_udp_hdr_t *udph_p = + (flwd_udp_hdr_t *)(buf + ip_hl); + + udph_p->uh_sum = 0; + /* 2012-03-19 LiJia add, for IPv6 */ + if(is_ipv6) + { + sum = sendpacket_in_cksum((u_int16_t *)&ip6h_p->ip6_src, 32); + } + else + { + sum = sendpacket_in_cksum((u_int16_t *)&iph_p->ip_src, 8); + } + sum += ntohs(IPPROTO_UDP + len); + sum += sendpacket_in_cksum((u_int16_t *)udph_p, len); + udph_p->uh_sum = SENDPACKET_CKSUM_CARRY(sum); + break; + } + + case IPPROTO_IP: /* Dummy protocol for TCP. */ + { + iph_p->ip_sum = 0; + sum = sendpacket_in_cksum((u_int16_t *)iph_p, len); + iph_p->ip_sum = SENDPACKET_CKSUM_CARRY(sum); + break; + } + + case IPPROTO_ICMP: + { + flwd_icmp_hdr_t *icmph_p = + (flwd_icmp_hdr_t *)(buf + ip_hl); + + icmph_p->icmp_sum = 0; + sum = sendpacket_in_cksum((u_short *)icmph_p, len); + icmph_p->icmp_sum = SENDPACKET_CKSUM_CARRY(sum); + break; + } + + default: + { + return (-1); + } + } + + return (1); +} + + + +/* + ߰İ(㲥鲥, DZIP,MACİ)ʶ𲢶. + + args: + check_dip_expect_cmp_res: ĿIPͱIPĹϵ, + user->acc_gatewayܼ, Ϊdip϶IP; + acc_gateway->fwd_gateway, fwd_gateway->acc_gateway, ΪǾͨ; + gdev->fwd_gateway, ʹmarsio, ʵ. +*/ +int flwd_rubbish_pkt_identify(flwd_device_handle_t *device_handle, + flwd_raw_pkt_t *raw_pkt, int check_dip_expect_cmp_res) +{ + const flwd_eth_hdr_t *eth_hdr = (const flwd_eth_hdr_t *)raw_pkt->outer_pkt_data; + flwd_ipv4_hdr_t *ip4hdr; + flwd_ipv6_hdr_t *ip6hdr; + unsigned eth_pro_type = ntohs(eth_hdr->h_proto); + + if(CAP_MODEL_SOCKET == device_handle->io_para.cap_mode){ + flwd_eth_hdr_t *inner_eth_hdr; + if((unsigned int)raw_pkt->inner_pkt_len < sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_vxlan_hdr_t)){ + return 1; + } + + inner_eth_hdr = (flwd_eth_hdr_t *)raw_pkt->inner_pkt_data; + if(ETH_P_IP == ntohs(inner_eth_hdr->h_proto)){ + ip4hdr = (flwd_ipv4_hdr_t *)(raw_pkt->inner_pkt_data + sizeof(flwd_eth_hdr_t)); + if(ip4hdr->ip_v != 4){ + return 1; + } + if(ip4hdr->ip_hl < 5){ + return 1; + } + if(ntohs(ip4hdr->ip_len) != (raw_pkt->inner_pkt_len - sizeof(flwd_eth_hdr_t))){ + return 1; + } + }else if(ETH_P_IPV6 != ntohs(inner_eth_hdr->h_proto)){ + ip6hdr = (flwd_ipv6_hdr_t *)(flwd_ipv6_hdr_t *)(raw_pkt->inner_pkt_data + sizeof(flwd_eth_hdr_t)); + if((ip6hdr->ip6_flags[0] & 0xF0) != 6){ + return 1; + } + if(ntohs(ip6hdr->ip6_payload_len) != (raw_pkt->inner_pkt_len - sizeof(flwd_eth_hdr_t) - sizeof(flwd_ipv6_hdr_t))){ + return 1; + } + }else{ + return 1; + } + } + + if(device_handle->io_para.cap_mode != CAP_MODEL_SOCKET){ /* ڻӲģʽ¼ */ + if(memcmp(G_FLWD_BROADCAST_ADDR, eth_hdr->h_dest, ETH_ALEN) == 0){ + if(ETH_P_ARP != eth_pro_type){ /* ǹ㲥ARP, ϶ӦóNAT, ֱӶ */ + return 1; + } + }else if(memcmp(device_handle->io_para.local_mac_addr, eth_hdr->h_dest, ETH_ALEN) != 0){ + /* ǹ㲥, ĿMACҲDZ, */ + return 1; + } + +#if 0 /* IPv6ھӷְʹ鲥ַʵ, IPv4ARP, Ҫ, ܶ */ + else if((eth_hdr->h_dest[0] & 0x01) == 0x01){ + /* 鲥MACַ, ͨΪڿݰ, LLMNR, SPTЭ, һ账 */ + return 1; + } +#endif + + if(ETH_P_IP == eth_pro_type){ + ip4hdr = (flwd_ipv4_hdr_t *)((char *)eth_hdr + sizeof(flwd_eth_hdr_t)); + + if(FLWD_IPV4_MULTICAST_ADDR(ntohl(ip4hdr->ip_dst.s_addr)) != 0){ + return 1; /* 鲥IPַ, */ + } + + if(check_dip_expect_cmp_res != (ip4hdr->ip_dst.s_addr == device_handle->io_para.device_ip_net_order)){ + return 1; + } + } + } + + return 0; +} + +static int flwd_protocol_stack_icmp_layer_process( + flwd_device_handle_t *io_handle, int tid, flwd_raw_pkt_t *raw_pkt, + flwd_ipv4_hdr_t *raw_ip_hdr, const flwd_simple_icmp_hdr_t *raw_icmp_hdr) +{ + int ret; + void *io_mbuff; + char *send_user_buf; + int raw_ip_tot_len = ntohs(raw_ip_hdr->ip_len); + int icmp_payload_len = raw_ip_tot_len - raw_ip_hdr->ip_hl * 4 - sizeof(flwd_simple_icmp_hdr_t); + + ///flwd_eth_hdr_t *snd_eth_hdr; + const flwd_eth_hdr_t *raw_eth_hdr = (const flwd_eth_hdr_t *)raw_pkt->outer_pkt_data; + + /* ΪӦͬײ, ڴ, ICMP_REPLYٷ, ֱ޸ԭʼ */ + io_mbuff = io_handle->low_level_mbuff_malloc(io_handle, tid, raw_pkt->outer_pkt_len); + assert(io_mbuff != NULL); + + send_user_buf = (char *)io_handle->low_level_mbuff_mtod(io_mbuff); + + flwd_sendpacket_build_icmpv4_echo(ICMP_ECHOREPLY, 0, 0, + raw_icmp_hdr->icd_id, + raw_icmp_hdr->icd_seq, + (char *)raw_icmp_hdr + sizeof(flwd_simple_icmp_hdr_t), + icmp_payload_len, + send_user_buf + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t)); + + flwd_sendpacket_build_ipv4(raw_ip_tot_len - sizeof(flwd_ipv4_hdr_t), + 0, + 0x1234, + 0, + 64, + IPPROTO_ICMP, + raw_ip_hdr->ip_dst.s_addr, /* ַȡ */ + raw_ip_hdr->ip_src.s_addr, /* ַȡ */ + NULL, + 0, + send_user_buf + sizeof(flwd_eth_hdr_t)); + + /* У */ + flwd_sendpacket_do_checksum(send_user_buf + sizeof(flwd_eth_hdr_t), + IPPROTO_IP, + sizeof(flwd_ipv4_hdr_t)); + + flwd_sendpacket_do_checksum(send_user_buf + sizeof(flwd_eth_hdr_t), + IPPROTO_ICMP, + icmp_payload_len + sizeof(flwd_simple_icmp_hdr_t)); + + flwd_sendpacket_build_ethernet(ETH_P_IP, raw_eth_hdr->h_dest, raw_eth_hdr->h_source, send_user_buf); + + io_handle->low_level_mbuff_set_pkt_len(io_mbuff, raw_pkt->outer_pkt_len); + + ret = io_handle->low_level_send(io_handle, tid, io_mbuff); + if(ret < 0){ + flwd_log(RLOG_LV_FATAL, "send icmp reply error!"); + }else{ + char icmp_dip_str[16]; + inet_ntop(AF_INET, &raw_ip_hdr->ip_dst.s_addr, icmp_dip_str, 16); + flwd_log(RLOG_LV_DEBUG, "ICMP: recv icmp request to %s, send icmp reply!\n", icmp_dip_str); + } + + io_handle->low_level_mbuff_free_after_send(io_handle, tid, io_mbuff); + + return ret; +} + + +static int flwd_protocol_stack_ipv4_layer_process( + flwd_device_handle_t *io_handle, int tid, flwd_raw_pkt_t *raw_pkt, flwd_ipv4_hdr_t *iphdr) +{ + const flwd_simple_icmp_hdr_t *flwd_simple_icmp_hdr; + + if(io_handle->io_para.device_ip_net_order != iphdr->ip_dst.s_addr){ + return 0; + } + + if(iphdr->ip_p != IPPROTO_ICMP){ + return 0; + } + + flwd_simple_icmp_hdr = (flwd_simple_icmp_hdr_t *)((char *)iphdr + iphdr->ip_hl * 4); + if(flwd_simple_icmp_hdr->icmp_type != ICMP_ECHO){ + return 0; + } + + flwd_protocol_stack_icmp_layer_process(io_handle, tid, raw_pkt, iphdr, flwd_simple_icmp_hdr); + + return 1; +} + + +static int flwd_protocol_stack_ipv6_layer_process( + flwd_device_handle_t *io_handle, int tid, flwd_raw_pkt_t *raw_pkt, flwd_ipv6_hdr_t *ip6hdr) +{ + if(IPPROTO_ICMPV6 == ip6hdr->ip6_nxt_hdr){ + /* TODO, + ICMPv6пǷNetighbor Э, + ȡIPַ, 鿴ǷDZ, + ȻظӦ. + */ + } + + return 0; +} + +static int flwd_protocol_stack_arp_layer_process( + flwd_device_handle_t *io_handle, int tid, flwd_raw_pkt_t *raw_pkt, flwd_arp_hdr_t *arp_hdr) +{ + int ret; + void *io_mbuff; + char *send_user_buf; + const flwd_eth_hdr_t *raw_eth_hdr; + + if(memcmp(arp_hdr->ar_tpa, &io_handle->io_para.device_ip_net_order, sizeof(int)) != 0){ + return 1; /* DZARP, Ҳ1, ⲿ߲ٴݰ, ҲظARPӦ */ + } + + if(arp_hdr->ar_op == htons(ARPOP_REPLY)){ + flwd_arp_response_update(arp_hdr); + return 1; + } + + if(arp_hdr->ar_op != htons(ARPOP_REQUEST)){ + /* ֻREQUESTREPLY, Ͳ */ + return 1; + } + + /* ΪӦͬײ, ڴ, ICMP_REPLYٷ, ֱ޸ԭʼ */ + io_mbuff = io_handle->low_level_mbuff_malloc(io_handle, tid, raw_pkt->outer_pkt_len); + assert(io_mbuff != NULL); + + send_user_buf = (char *)io_handle->low_level_mbuff_mtod(io_mbuff); + + flwd_sendpacket_build_arp(ARPHRD_ETHER, ETH_P_IP, arp_hdr->ar_hln, arp_hdr->ar_pln, + ARPOP_REPLY, + io_handle->io_para.local_mac_addr, + arp_hdr->ar_tpa, + arp_hdr->ar_sha, + arp_hdr->ar_spa, + send_user_buf + sizeof(flwd_eth_hdr_t)); + + raw_eth_hdr = (const flwd_eth_hdr_t *)raw_pkt->outer_pkt_data; + flwd_sendpacket_build_ethernet(ETH_P_ARP, io_handle->io_para.local_mac_addr, + raw_eth_hdr->h_source, send_user_buf); + + io_handle->low_level_mbuff_set_pkt_len(io_mbuff, raw_pkt->outer_pkt_len); + + ret = io_handle->low_level_send(io_handle, tid, io_mbuff); + if(ret < 0){ + flwd_log(RLOG_LV_FATAL, "send arp reply error!"); + }else{ + char arp_dip_str[16]; + inet_ntop(AF_INET, arp_hdr->ar_tpa, arp_dip_str, 16); + flwd_log(RLOG_LV_DEBUG, "ARP: recv arp request to %s, send arp reply!\n", arp_dip_str); + } + + io_handle->low_level_mbuff_free_after_send(io_handle, tid, io_mbuff); + + return 1; /* ARPЭ϶flowoodģҪ, DzDZ, ̶1 */ +} + +/* + IPЭջ, arp, icmp. + return value: + 1: Эջ, flowoodģ; + 0: Эջ, IP. +*/ +int flwd_protocol_stack_process(flwd_device_handle_t *io_handle, + int tid, flwd_raw_pkt_t *raw_pkt) +{ + int is_stack = 0; + + const flwd_eth_hdr_t *flwd_ethhdr = (const flwd_eth_hdr_t *)raw_pkt->outer_pkt_data; + + switch(ntohs(flwd_ethhdr->h_proto)){ + case ETH_P_IP: + is_stack = flwd_protocol_stack_ipv4_layer_process(io_handle, tid, raw_pkt, (flwd_ipv4_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t))); + flwd_thread_val[tid].pkt_stat.ip_pkt_num++; + flwd_thread_val[tid].pkt_stat.ip_pkt_byte += raw_pkt->outer_pkt_len; + break; + + case ETH_P_IPV6: + is_stack = flwd_protocol_stack_ipv6_layer_process(io_handle, tid, raw_pkt, (flwd_ipv6_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t))); + break; + + case ETH_P_ARP: + is_stack = flwd_protocol_stack_arp_layer_process(io_handle, tid, raw_pkt, (flwd_arp_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t))); + break; + + default: + break; + } + + return is_stack; +} + diff --git a/src/common/flwd_common_tool.c b/src/common/flwd_common_tool.c new file mode 100644 index 0000000..e2e1b36 --- /dev/null +++ b/src/common/flwd_common_tool.c @@ -0,0 +1,911 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_handle_logger.h" +#include "stream.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +static const unsigned char flwd_adapt_sleep_time_table[100] = +{ + 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ϊpollģʽ, ɹɹհ30%, ˵ϵͳرȽ, Ͳusleep */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + + +void flwd_adapt_sleep(int success_work_times_in_recent_100) +{ + assert(success_work_times_in_recent_100 < 100); + + if(flwd_adapt_sleep_time_table[success_work_times_in_recent_100] > 0){ + usleep(flwd_adapt_sleep_time_table[success_work_times_in_recent_100]); + } +} + + +flwd_ip_region_type_t flwd_ipv4_location(unsigned int ip4addr_host_order) +{ + +#if FLWD_RUN_IN_CEIEC_TEST + /* ڲԵַж!!! */ + if((ip4addr_host_order & 0xFFFFFF00) == 0xAC100A00){ /* 172.16.10.5Ϊ, λ */ + return FLWD_IP_REGION_OUTLAND; + } + if((ip4addr_host_order & 0xFFFFFF00) == 0xAC100B00){/* 172.16.11.xxΪͻIP, λ */ + return FLWD_IP_REGION_INLAND; + } +#endif + /* TODO, IPַжϵλ, ˴дڲIP */ + if(((ip4addr_host_order & 0xFF000000) == 0x0a000000) /* 10/8 */ + ||((ip4addr_host_order & 0xFFF00000) == 0xAC100000 ) /* 172.16/12 */ + ||((ip4addr_host_order & 0xFFFF0000) == 0xC0A80000)){ /* 192.168/16 */ + return FLWD_IP_REGION_INLAND; + } + + return FLWD_IP_REGION_OUTLAND; +} + +flwd_ip_region_type_t flwd_ipv6_location(const struct in6_addr *ip6addr_net) +{ + /* TODO, IPַ */ + + return FLWD_IP_REGION_INLAND; +} + + +/* ͨIPַλ, õǰʵĿIPڵλ */ +flwd_ip_region_type_t flwd_dstip_location(const flwd_tuple5_t *tuple5) +{ + unsigned int actual_dip_v4_host; + + if(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type){ + if(tuple5->dir_reverse != 0){ + actual_dip_v4_host = ntohl(tuple5->ippair_v4.sip_net_order); + }else{ + actual_dip_v4_host = ntohl(tuple5->ippair_v4.dip_net_order); + } + + return flwd_ipv4_location(actual_dip_v4_host); + }else{ + /* TODO, IPv6 */ + flwd_log(30, "recv ipv6 packet, but not support ipv6 addr location yet!\n"); + return FLWD_IP_REGION_INLAND; + } + + return FLWD_IP_REGION_INLAND; +} + + +const char *flwd_ip_region_ntop(int ip_region_type) +{ + if((int)FLWD_IP_REGION_INLAND == ip_region_type){ + return "inland"; + } + + return "outland"; +} + + +const char *flwd_tuple5_ntop(int tid, const flwd_tuple5_t *tuple5) +{ + static char str_mbuf[FLWD_MAX_THREAD_NUM][256]; + char ip_src_str[64], ip_dst_str[64]; + unsigned short actual_sport, actual_dport; + + if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type)){ + if(tuple5->dir_reverse){ + inet_ntop(AF_INET, &tuple5->ippair_v4.dip_net_order, ip_src_str, 64); + inet_ntop(AF_INET, &tuple5->ippair_v4.sip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->dport_net_order); + actual_dport = ntohs(tuple5->sport_net_order); + }else{ + inet_ntop(AF_INET, &tuple5->ippair_v4.sip_net_order, ip_src_str, 64); + inet_ntop(AF_INET, &tuple5->ippair_v4.dip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->sport_net_order); + actual_dport = ntohs(tuple5->dport_net_order); + } + }else{ + if(tuple5->dir_reverse){ + inet_ntop(AF_INET6, &tuple5->ippair_v6->dip_net_order, ip_src_str, 64); + inet_ntop(AF_INET6, &tuple5->ippair_v6->sip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->dport_net_order); + actual_dport = ntohs(tuple5->sport_net_order); + }else{ + inet_ntop(AF_INET6, &tuple5->ippair_v6->sip_net_order, ip_src_str, 64); + inet_ntop(AF_INET6, &tuple5->ippair_v6->dip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->sport_net_order); + actual_dport = ntohs(tuple5->dport_net_order); + } + } + + snprintf(str_mbuf[tid], 256, "%s.%u > %s.%u", ip_src_str, actual_sport, + ip_dst_str, actual_dport); + + return str_mbuf[tid]; +} + + +const char *flwd_tuple5_ntop_r(const flwd_tuple5_t *tuple5, char *str_mbuf, int mbuf_len) +{ + char ip_src_str[64], ip_dst_str[64]; + unsigned short actual_sport, actual_dport; + + if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type)){ + if(tuple5->dir_reverse){ + inet_ntop(AF_INET, &tuple5->ippair_v4.dip_net_order, ip_src_str, 64); + inet_ntop(AF_INET, &tuple5->ippair_v4.sip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->dport_net_order); + actual_dport = ntohs(tuple5->sport_net_order); + }else{ + inet_ntop(AF_INET, &tuple5->ippair_v4.sip_net_order, ip_src_str, 64); + inet_ntop(AF_INET, &tuple5->ippair_v4.dip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->sport_net_order); + actual_dport = ntohs(tuple5->dport_net_order); + } + }else{ + if(tuple5->dir_reverse){ + inet_ntop(AF_INET6, &tuple5->ippair_v6->dip_net_order, ip_src_str, 64); + inet_ntop(AF_INET6, &tuple5->ippair_v6->sip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->dport_net_order); + actual_dport = ntohs(tuple5->sport_net_order); + }else{ + inet_ntop(AF_INET6, &tuple5->ippair_v6->sip_net_order, ip_src_str, 64); + inet_ntop(AF_INET6, &tuple5->ippair_v6->dip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->sport_net_order); + actual_dport = ntohs(tuple5->dport_net_order); + } + } + + snprintf(str_mbuf, mbuf_len, "%s.%u > %s.%u", + ip_src_str, actual_sport, + ip_dst_str, actual_dport); + + return str_mbuf; +} + +/* + жflwd_ip_tַǷ. + 1:ͬ; + 0:ͬ; +*/ +int flwd_ipt_equal(const flwd_ip_t *ip1, const flwd_ip_t *ip2) +{ + int diff = 0; + if(ip1->addr_type != ip2->addr_type){ + return 0; + } + + if(FLWD_IP_ADDR_TYPE_V4 == ip1->addr_type){ + if(ip1->addr_ipv4 == ip2->addr_ipv4){ + diff = 1; + }else{ + diff = 0; + } + }else{ + if(memcmp(&ip1->addr_ipv6, &ip2->addr_ipv6, sizeof(struct in6_addr)) == 0){ + diff = 1; + }else{ + diff = 0; + } + } + + return diff; +} + + +const char *flwd_ipt_ntop_r(const flwd_ip_t *ipbin, char *str_mbuf, int mbuf_len) +{ + ///char ip_str[64]; + + if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == ipbin->addr_type)){ + inet_ntop(AF_INET, &ipbin->addr_ipv4, str_mbuf, mbuf_len); + }else{ + inet_ntop(AF_INET6, &ipbin->addr_ipv6, str_mbuf, mbuf_len); + } + + return str_mbuf; +} + +/* + ַmemcpy, + ַָָǰ̵߳ȫֱ, ֻڵǰջʹ, غַʧЧ. +*/ +flwd_tuple5_t *flwd_tuple5_dup_to_stack(int tid, flwd_tuple5_t *dst_tuple5, const flwd_tuple5_t *src_tuple5) +{ + memcpy(dst_tuple5, src_tuple5, sizeof(flwd_tuple5_t)); + + if(FLWD_IP_ADDR_TYPE_V6 == src_tuple5->addr_type){ + memcpy(&flwd_thread_val[tid].nat_key_ipv6_buf, src_tuple5->ippair_v6, sizeof(flwd_ippair_v6_t)); + dst_tuple5->ippair_v6 = &flwd_thread_val[tid].nat_key_ipv6_buf; + } + + return dst_tuple5; +} + +/* + ַmemcpy, + ַָָmallocȫڴ, ʹúעfree. +*/ +flwd_tuple5_t *flwd_tuple5_dup_to_heap(flwd_tuple5_t *dst_tuple5, const flwd_tuple5_t *src_tuple5) +{ + memcpy(dst_tuple5, src_tuple5, sizeof(flwd_tuple5_t)); + + if(FLWD_IP_ADDR_TYPE_V6 == src_tuple5->addr_type){ + dst_tuple5->ippair_v6 = (flwd_ippair_v6_t *)malloc(sizeof(flwd_ippair_v6_t)); + memcpy(dst_tuple5->ippair_v6, src_tuple5->ippair_v6, sizeof(flwd_ippair_v6_t)); + } + + return dst_tuple5; +} + +/* + Ϊtuple5Ĵ洢Ϊ˷hash, ʹôַΪԴĬϹ, ܵߵʵԪķ, + ˺dirķ, ָԭʼԪ, sip϶ԭʼԴIP! +*/ +void flwd_tuple5_adjust_dir(flwd_tuple5_t *tuple5) +{ + unsigned short tshort; + unsigned int tint; + struct in6_addr tin6; + + if(0 == tuple5->dir_reverse){ + return; + } + + tshort = tuple5->sport_net_order; + tuple5->sport_net_order = tuple5->dport_net_order; + tuple5->dport_net_order = tshort; + + if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type)){ + tint = tuple5->ippair_v4.sip_net_order; + tuple5->ippair_v4.sip_net_order = tuple5->ippair_v4.dip_net_order; + tuple5->ippair_v4.dip_net_order = tint; + }else{ + memcpy(&tin6, &tuple5->ippair_v6->sip_net_order, sizeof(struct in6_addr)); + memcpy(&tuple5->ippair_v6->sip_net_order, &tuple5->ippair_v6->dip_net_order, sizeof(struct in6_addr)); + memcpy(&tuple5->ippair_v6->dip_net_order, &tin6, sizeof(struct in6_addr)); + } + + return; +} + + +void *flwd_calloc(int tid, size_t nmemb, size_t size) +{ + /* todo: dictator */ + return calloc(nmemb, size); +} + + +void *flwd_malloc(int tid, size_t size) +{ + /* todo: dictator */ + return malloc(size); +} + + +void flwd_free(int tid, void *ptr) +{ + /* todo: dictator */ + free(ptr); +} + +static int inline flwd_build_tuple4v4_key(flwd_tuple5_t *nat_key_v4, const flwd_raw_pkt_t *raw_pkt) +{ + const flwd_ipv4_hdr_t *flwd_iphdr = (flwd_ipv4_hdr_t *)raw_pkt->inner_ip_layer_hdr; + unsigned short raw_sport, raw_dport; + const flwd_tcp_hdr_t *flwd_tcphdr; + const flwd_udp_hdr_t *flwd_udphdr; + + nat_key_v4->addr_type = FLWD_IP_ADDR_TYPE_V4; + + if(IPPROTO_TCP == flwd_iphdr->ip_p){ + flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_iphdr + flwd_iphdr->ip_hl * 4); + raw_sport = flwd_tcphdr->th_sport; + raw_dport = flwd_tcphdr->th_dport; + nat_key_v4->protocol = IPPROTO_TCP; + }else if(IPPROTO_UDP == flwd_iphdr->ip_p){ + flwd_udphdr = (flwd_udp_hdr_t *)((char *)flwd_iphdr + flwd_iphdr->ip_hl * 4); + raw_sport = flwd_udphdr->uh_sport; + raw_dport = flwd_udphdr->uh_dport; + nat_key_v4->protocol = IPPROTO_UDP; + }else{ + flwd_log(30, "ip protocol is:%d, not support yet!\n", flwd_iphdr->ip_p); + return -1; + } + + /* keyĶ: + IPַΪԴ, ַһ, ˿ڴΪԴ, + ǸԴ涨, ν˭С, + ΪЧ, ֱʹֵַȽϴС, ÿζntoh任; + */ + if(flwd_iphdr->ip_src.s_addr > flwd_iphdr->ip_dst.s_addr){ + nat_key_v4->ippair_v4.sip_net_order = flwd_iphdr->ip_src.s_addr; + nat_key_v4->ippair_v4.dip_net_order = flwd_iphdr->ip_dst.s_addr; + nat_key_v4->sport_net_order = raw_sport; + nat_key_v4->dport_net_order = raw_dport; + nat_key_v4->dir_reverse = 0; + }else if(flwd_iphdr->ip_src.s_addr < flwd_iphdr->ip_dst.s_addr){ + nat_key_v4->ippair_v4.sip_net_order = flwd_iphdr->ip_dst.s_addr; + nat_key_v4->ippair_v4.dip_net_order = flwd_iphdr->ip_src.s_addr; + nat_key_v4->sport_net_order = raw_dport; + nat_key_v4->dport_net_order = raw_sport; + nat_key_v4->dir_reverse = 1; + }else{ + if(raw_sport > raw_dport){ + nat_key_v4->ippair_v4.sip_net_order = flwd_iphdr->ip_src.s_addr; + nat_key_v4->ippair_v4.dip_net_order = flwd_iphdr->ip_dst.s_addr; + nat_key_v4->sport_net_order = raw_sport; + nat_key_v4->dport_net_order = raw_dport; + nat_key_v4->dir_reverse = 0; + }else{ + nat_key_v4->ippair_v4.sip_net_order = flwd_iphdr->ip_dst.s_addr; + nat_key_v4->ippair_v4.dip_net_order = flwd_iphdr->ip_src.s_addr; + nat_key_v4->sport_net_order = raw_dport; + nat_key_v4->dport_net_order = raw_sport; + nat_key_v4->dir_reverse = 1; + } + } + + return nat_key_v4->dir_reverse; +} + +static inline int flwd_build_tuple4v6_key(int tid, flwd_tuple5_t *nat_key_v6, const flwd_raw_pkt_t *raw_pkt) +{ + const flwd_ipv6_hdr_t *flwd_ip6hdr = (flwd_ipv6_hdr_t *)raw_pkt->inner_ip_layer_hdr; + unsigned short raw_sport, raw_dport; + const flwd_tcp_hdr_t *flwd_tcphdr; + const flwd_udp_hdr_t *flwd_udphdr; + flwd_ippair_v6_t *nat_key_ipv6_buf = &flwd_thread_val[tid].nat_key_ipv6_buf; /* ջʱַ, ʹȫֱĻ, malloc/free */ + int diff; + + nat_key_v6->addr_type = FLWD_IP_ADDR_TYPE_V6; + + if(IPPROTO_TCP == flwd_ip6hdr->ip6_nxt_hdr){ + flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_ip6hdr + sizeof(flwd_ipv6_hdr_t)); + raw_sport = flwd_tcphdr->th_sport; + raw_dport = flwd_tcphdr->th_dport; + nat_key_v6->protocol = IPPROTO_TCP; + }if(IPPROTO_UDP == flwd_ip6hdr->ip6_nxt_hdr){ + flwd_udphdr = (flwd_udp_hdr_t *)((char *)flwd_ip6hdr + sizeof(flwd_ipv6_hdr_t)); + raw_sport = flwd_udphdr->uh_sport; + raw_dport = flwd_udphdr->uh_dport; + nat_key_v6->protocol = IPPROTO_UDP; + }else{ + /* Эݲ֧ */ + return -1; + } + + nat_key_v6->ippair_v6 = nat_key_ipv6_buf; + + /* keyĶ: + IPַΪԴ, ַһ, ˿ڴΪԴ, + ΪǸԴ涨, ν˭С, + ΪЧ, ֱʹֵַȽϴС, ÿζntoh任; + */ + diff = memcmp(&flwd_ip6hdr->ip6_src, &flwd_ip6hdr->ip6_dst, sizeof( struct in6_addr)); + if(diff > 0){ + memcpy(&nat_key_ipv6_buf->sip_net_order, &flwd_ip6hdr->ip6_src, sizeof( struct in6_addr)); + memcpy(&nat_key_ipv6_buf->dip_net_order, &flwd_ip6hdr->ip6_dst, sizeof( struct in6_addr)); + nat_key_v6->sport_net_order = raw_sport; + nat_key_v6->dport_net_order = raw_dport; + nat_key_v6->dir_reverse = 0; + }else if(diff < 0){ + memcpy(&nat_key_ipv6_buf->sip_net_order, &flwd_ip6hdr->ip6_dst, sizeof( struct in6_addr)); + memcpy(&nat_key_ipv6_buf->dip_net_order, &flwd_ip6hdr->ip6_src, sizeof( struct in6_addr)); + nat_key_v6->sport_net_order = raw_dport; + nat_key_v6->dport_net_order = raw_sport; + nat_key_v6->dir_reverse = 1; + }else{ + if(raw_sport > raw_dport){ + memcpy(&nat_key_ipv6_buf->sip_net_order, &flwd_ip6hdr->ip6_src, sizeof( struct in6_addr)); + memcpy(&nat_key_ipv6_buf->dip_net_order, &flwd_ip6hdr->ip6_dst, sizeof( struct in6_addr)); + nat_key_v6->sport_net_order = raw_sport; + nat_key_v6->dport_net_order = raw_dport; + nat_key_v6->dir_reverse = 0; + }else{ + memcpy(&nat_key_ipv6_buf->sip_net_order, &flwd_ip6hdr->ip6_dst, sizeof( struct in6_addr)); + memcpy(&nat_key_ipv6_buf->dip_net_order, &flwd_ip6hdr->ip6_src, sizeof( struct in6_addr)); + nat_key_v6->sport_net_order = raw_dport; + nat_key_v6->dport_net_order = raw_sport; + nat_key_v6->dir_reverse = 1; + } + } + + return 0; +} + +/* + TODO: + IPƬô? DNSӦ, жadditionl-records, ͳMTU,ҪƬ. + NATkeyԪ, IPƬֻеһƬЯ˿, (ƬС20ֽ, TCPͷҲȫ, װҲûж˿), + + ȡ: ȽIPƬ, ɺ, NATת, ʱƬ. + + HASHʱ, + ΪSNAT->C2S, SNAT->S2C, DNAT->C2S, DNAT->S2C, + ĵַͬ, + , һӵڲַⲿַ˵, Ҫkey, ָͬһnat_info. + + return value: + 1: keyĵַԭʵԪ˷ת; + 0: keyĵַʵԪַ; +*/ +int flwd_build_tuple4_key(int tid, flwd_tuple5_t *nat_key, const flwd_raw_pkt_t *raw_pkt) +{ + int ret; + const flwd_eth_hdr_t *flwd_ethhdr = (flwd_eth_hdr_t *)raw_pkt->inner_pkt_data; + unsigned short eth_type = ntohs(flwd_ethhdr->h_proto); + + if(ETH_P_IP == eth_type){ + ret = flwd_build_tuple4v4_key(nat_key, raw_pkt); + }else if(ETH_P_IPV6 == eth_type){ + ret = flwd_build_tuple4v6_key(tid, nat_key, raw_pkt); + }else{ + /* unsuport or unknown protocol */ + //flwd_log(20, "unsupport ethernet protocol, 0x%x", eth_type); + ret = -1; + } + + return ret; +} + +/* + IPϵͳڲַƽ̨, Maatַṹһ, ɨ֮ǰҪת. +*/ +int flwd_tuple5_to_stream_addr(int tid, const flwd_tuple5_t *tuple5, struct ipaddr *stream_addr) +{ + if(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type){ + stream_addr->addrtype = ADDR_TYPE_IPV4; + stream_addr->addrlen = sizeof(int); + if(0 == tuple5->dir_reverse){ + flwd_thread_val[tid].addrv4_convert_buf.saddr = tuple5->ippair_v4.sip_net_order; + flwd_thread_val[tid].addrv4_convert_buf.daddr = tuple5->ippair_v4.dip_net_order; + flwd_thread_val[tid].addrv4_convert_buf.source = tuple5->sport_net_order; + flwd_thread_val[tid].addrv4_convert_buf.dest = tuple5->dport_net_order; + }else{ + flwd_thread_val[tid].addrv4_convert_buf.saddr = tuple5->ippair_v4.dip_net_order; + flwd_thread_val[tid].addrv4_convert_buf.daddr = tuple5->ippair_v4.sip_net_order; + flwd_thread_val[tid].addrv4_convert_buf.source = tuple5->dport_net_order; + flwd_thread_val[tid].addrv4_convert_buf.dest = tuple5->sport_net_order; + } + + stream_addr->v4 = &flwd_thread_val[tid].addrv4_convert_buf; + }else{ + stream_addr->addrtype = ADDR_TYPE_IPV6; + stream_addr->addrlen = sizeof(sizeof(struct in6_addr)); + if(0 == tuple5->dir_reverse){ + memcpy(flwd_thread_val[tid].addrv6_convert_buf.saddr, &tuple5->ippair_v6->sip_net_order, sizeof(struct in6_addr)); + memcpy(flwd_thread_val[tid].addrv6_convert_buf.daddr, &tuple5->ippair_v6->dip_net_order, sizeof(struct in6_addr)); + flwd_thread_val[tid].addrv6_convert_buf.source = tuple5->sport_net_order; + flwd_thread_val[tid].addrv6_convert_buf.dest = tuple5->dport_net_order; + }else{ + memcpy(flwd_thread_val[tid].addrv6_convert_buf.saddr, &tuple5->ippair_v6->dip_net_order, sizeof(struct in6_addr)); + memcpy(flwd_thread_val[tid].addrv6_convert_buf.daddr, &tuple5->ippair_v6->sip_net_order, sizeof(struct in6_addr)); + flwd_thread_val[tid].addrv6_convert_buf.source = tuple5->dport_net_order; + flwd_thread_val[tid].addrv6_convert_buf.dest = tuple5->sport_net_order; + } + + stream_addr->v6 = &flwd_thread_val[tid].addrv6_convert_buf; + } + + return 0; +} + +/* + յԭʼ, Ԥ, ݲģʽ, topģʽͬ, òַָͬ. + +*/ +int flwd_pre_process_pkt_input(flwd_device_handle_t *rcv_device_handle, flwd_raw_pkt_t *raw_pkt) +{ + if((TOPO_ACC_LINK_FWD == rcv_device_handle->io_para.topo_mode) + || (TOPO_FWD_LINK_ACC == rcv_device_handle->io_para.topo_mode)){ + /* شתطհ, vxlan. */ + 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; + }else if(TOPO_ACC_LINK_USER == rcv_device_handle->io_para.topo_mode){ + /* û˽붼ͨEthernet, TODO, tap豸??? */ + raw_pkt->inner_ip_layer_hdr = (const char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t); + raw_pkt->inner_pkt_data = (char *)raw_pkt->outer_pkt_data; + raw_pkt->inner_pkt_len = raw_pkt->outer_pkt_len; + }else if(TOPO_FWD_LINK_GDEV == rcv_device_handle->io_para.topo_mode){ +#if FLWD_NO_GDEV_ENV + raw_pkt->inner_ip_layer_hdr = (const char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t); + raw_pkt->inner_pkt_data = (char *)raw_pkt->outer_pkt_data; + raw_pkt->inner_pkt_len = raw_pkt->outer_pkt_len; +#else + /* mrtunnatѾжvxlanͷ */ + raw_pkt->inner_ip_layer_hdr = (const char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t); + raw_pkt->inner_pkt_data = (char *)raw_pkt->outer_pkt_data; + raw_pkt->inner_pkt_len = raw_pkt->outer_pkt_len; +#endif + } + + return 0; +} + + +/* + dynamic, static, htableݵķʽһ, Ҫ. +*/ +flwd_active_ip_t *flwd_ip_pool_search(unsigned char act_ip_origin, const MESA_htable_handle table, const uchar * key, uint size) +{ + flwd_active_ip_t *act_ip_list_head; + + if(FLWD_ACT_IP_DYNAMIC == act_ip_origin){ + return (flwd_active_ip_t *)MESA_htable_search(table, key, size); + } + + /* ̬IPgroup_idΪkey, IP_listΪdata */ + act_ip_list_head = (flwd_active_ip_t *)MESA_htable_search(table, key, size); +#if 1 + return act_ip_list_head; +#else + if(NULL == act_ip_list_head){ + return NULL; + } + + tmp_ip = act_ip_list_head; + do{ + /* ʹ֮Ƚϳipv6ıַбȽ */ + if(memcmp(key, &tmp_ip->active_ip_net_order.addr_ipv6, size) == 0){ + break; + } + if(tmp_ip->active_ip_list_node.nextele){ + tmp_ip = (flwd_active_ip_t *)tmp_ip->active_ip_list_node.nextele->quiddity; + }else{ + tmp_ip = NULL; + break; + } + }while(tmp_ip != act_ip_list_head); + + return tmp_ip; +#endif +} + + +static void __phony_del_cb(void *arg) +{ + return; /* ֻɾhtableṹkey, ɾdata */ +} + +/* + TODO: dynamic, static, htableݵķʽһ, Ҫ. +*/ +void flwd_ip_pool_del(unsigned char act_ip_origin, MESA_htable_handle table, unsigned int policy_group_id, + void (* del_cb)(void *), const flwd_active_ip_t *maat_cb_tobe_del_ip) +{ + flwd_active_ip_t *act_ip_list_head, *tmp_ip; + MESA_list_t *list_node; + ///flwd_active_ip_t *in_htable_tobe_del_ip; + const unsigned char *hkey; + unsigned int hsize; + unsigned char static_ip_group_key[64]; + int static_ip_group_key_len = 64; + int found = 0; + int to_be_free_group_id_key = 0; + char ip_str[64]; + + /* ̬IPֱɾ */ + if(FLWD_ACT_IP_DYNAMIC == act_ip_origin){ + MESA_htable_del(table, (unsigned char *)&maat_cb_tobe_del_ip->active_ip_net_order.addr_value, maat_cb_tobe_del_ip->active_ip_net_order.addr_len, del_cb); + return; + } + + flwd_policy_group_id_key_gen(policy_group_id, static_ip_group_key, &static_ip_group_key_len); + + act_ip_list_head = (flwd_active_ip_t *)MESA_htable_search(table, static_ip_group_key, static_ip_group_key_len); + if(NULL == act_ip_list_head){ + flwd_log(30, "del static ip pool, but '%s' not in htable!\n", flwd_ipt_ntop_r(&maat_cb_tobe_del_ip->active_ip_net_order, ip_str, 64)); + return; + } + + if(FLWD_IP_ADDR_TYPE_V4 == maat_cb_tobe_del_ip->active_ip_net_order.addr_type){ + hkey = (unsigned char *)&maat_cb_tobe_del_ip->active_ip_net_order.addr_ipv4; + hsize = sizeof(int); + }else{ + hkey = (unsigned char *)&maat_cb_tobe_del_ip->active_ip_net_order.addr_ipv6; + hsize = sizeof(struct in6_addr); + } + + list_node = &act_ip_list_head->active_ip_list_node; + + do{ + tmp_ip = (flwd_active_ip_t *)list_node->quiddity; + if(memcmp(hkey, &tmp_ip->active_ip_net_order.addr_value, hsize) == 0){ + found = 1; + break; + } + list_node = list_node->nextele; + }while(list_node != &act_ip_list_head->active_ip_list_node); + + if(found != 0){ + if(MESA_list_is_empty(&act_ip_list_head->active_ip_list_node)){ + /* ˴emptyʾֻһͷڵ, IRϵͳ˵, ͷڵҲ洢, empty! */ + to_be_free_group_id_key = 1; + } + + MESA_list_del(&act_ip_list_head->active_ip_list_node, &tmp_ip->active_ip_list_node); + + /* ˴ֻhtableɾip_keyݽṹ, ʵʵdataact_ip_list_head, ɾ, IPɾɾip_list */ + MESA_htable_del(table, hkey, hsize, __phony_del_cb); + + del_cb((void *)tmp_ip); /* ɾIP */ + + if(to_be_free_group_id_key != 0){ + /* static_poolǰpolicy_idɾһIP, Ѿ, ҪHASHɾpolicy_idΪkeyĽṹ */ + MESA_htable_del(table, static_ip_group_key, strlen((const char *)static_ip_group_key), __phony_del_cb); + } + } + + return; +} + + +void flwd_del_last_rn(char *data, int max_len) +{ + int i; + for(i = 0; i < max_len; i++){ + if(('\r' == data[i]) || ('\n' == data[i])){ + data[i] = '\0'; + return; + } + } + + return; +} + + +unsigned char *flwd_policy_group_id_key_gen(unsigned int policy_group_id, unsigned char *out_key, int *out_key_len) +{ + int actual_key_len; + + if(NULL == out_key_len || *out_key_len < 16){ + return (unsigned char *)"ERROR"; + } + + actual_key_len = snprintf((char *)out_key, *out_key_len, "GPID%u", policy_group_id); + + *out_key_len = actual_key_len; + + return out_key; +} + + +/* + sapp, ӡǰԪ, ֱʹprintadd, ΪʱܻߵԴĿַ. +*/ +const char *flwd_debug_print_tuple4(const void *a_packet, int tid) +{ + char debug_ip_src_str[64], debug_ip_dst_str[64]; + unsigned short debug_sport, debug_dport; + const flwd_ipv4_hdr_t *ipv4_hdr; + const flwd_ipv6_hdr_t *ipv6_hdr; + const flwd_tcp_hdr_t *thdr; + const flwd_udp_hdr_t *uhdr; + static char tuple4_str[FLWD_MAX_THREAD_NUM][128]; + unsigned char *ip_hdr = (unsigned char *)a_packet; + unsigned char protocol; + + if(tid >= FLWD_MAX_THREAD_NUM){ + assert(0); + } + + if(NULL == a_packet){ + return "NULL"; + } + + if(flwd_cfg_val.flwd_log_level <= 10){ + if(0x40 == (ip_hdr[0] & 0xF0)){ /* sappIPͷ, Իȡraw_pkt, ߿IPͷһIPV4IPV6 */ + ipv4_hdr = (flwd_ipv4_hdr_t *)a_packet; + protocol = ipv4_hdr->ip_p; + }else{ + ipv6_hdr = (flwd_ipv6_hdr_t *)a_packet; + protocol = ipv6_hdr->ip6_nxt_hdr; + } + + inet_ntop(AF_INET, &ipv4_hdr->ip_src.s_addr, debug_ip_src_str, 64); + inet_ntop(AF_INET, &ipv4_hdr->ip_dst.s_addr, debug_ip_dst_str, 64); + if(6 == protocol){ + thdr = (flwd_tcp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(thdr->th_sport); + debug_dport = ntohs(thdr->th_dport); + }else if (17 == protocol){ + uhdr = (flwd_udp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(uhdr->uh_sport); + debug_dport = ntohs(uhdr->uh_dport); + }else{ + debug_sport = 0; + debug_dport = 0; + } + } + + snprintf(tuple4_str[tid], 128, "%s,%u ---> %s,%u", debug_ip_src_str, debug_sport, debug_ip_dst_str, debug_dport); + + return tuple4_str[tid]; +} + + +/* + sapp, ӡǰԪ, IPID, UDP_CHECKSUMΨһʶһϢ, + DEBUGλ. +*/ +const char *flwd_debug_print_tuple4_detail(const void *a_packet, int tid) +{ + char debug_ip_src_str[64], debug_ip_dst_str[64]; + unsigned short debug_sport, debug_dport; + const flwd_ipv4_hdr_t *ipv4_hdr; + const flwd_ipv6_hdr_t *ipv6_hdr; + const flwd_tcp_hdr_t *thdr; + const flwd_udp_hdr_t *uhdr; + static char tuple4_str[FLWD_MAX_THREAD_NUM][256]; + unsigned char *ip_hdr = (unsigned char *)a_packet; + unsigned char protocol; + unsigned short ip_id; + unsigned short tu_checksum; + + if(tid >= FLWD_MAX_THREAD_NUM){ + assert(0); + } + + if(NULL == a_packet){ + return "NULL"; + } + + if(flwd_cfg_val.flwd_log_level <= 10){ + if(0x40 == (ip_hdr[0] & 0xF0)){ /* sappIPͷ, Իȡraw_pkt, ߿IPͷһIPV4IPV6 */ + ipv4_hdr = (flwd_ipv4_hdr_t *)a_packet; + protocol = ipv4_hdr->ip_p; + ip_id = ntohs(ipv4_hdr->ip_id); + }else{ + ipv6_hdr = (flwd_ipv6_hdr_t *)a_packet; + protocol = ipv6_hdr->ip6_nxt_hdr; + ip_id = 0; + } + + inet_ntop(AF_INET, &ipv4_hdr->ip_src.s_addr, debug_ip_src_str, 64); + inet_ntop(AF_INET, &ipv4_hdr->ip_dst.s_addr, debug_ip_dst_str, 64); + if(6 == protocol){ + thdr = (flwd_tcp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(thdr->th_sport); + debug_dport = ntohs(thdr->th_dport); + tu_checksum = ntohs(thdr->th_sum); + }else if (17 == protocol){ + uhdr = (flwd_udp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(uhdr->uh_sport); + debug_dport = ntohs(uhdr->uh_dport); + tu_checksum = ntohs(uhdr->uh_sum); + }else{ + debug_sport = 0; + debug_dport = 0; + } + } + + snprintf(tuple4_str[tid], 256, "%s,%u ---> %s,%u, pro:%u, ipid:0x%04x, checksum:0x%04x", + debug_ip_src_str, debug_sport, debug_ip_dst_str, debug_dport, + protocol, + ip_id, + tu_checksum); + + return tuple4_str[tid]; +} + + +/* + sapp, ӡǰԪ, IPID, UDP_CHECKSUMΨһʶһϢ, + DEBUGλ. +*/ +const char *flwd_debug_print_tuple4_detail_r(const void *a_packet, char *buf, int buf_max_len) +{ + char debug_ip_src_str[64], debug_ip_dst_str[64]; + unsigned short debug_sport, debug_dport; + const flwd_ipv4_hdr_t *ipv4_hdr; + const flwd_ipv6_hdr_t *ipv6_hdr; + const flwd_tcp_hdr_t *thdr; + const flwd_udp_hdr_t *uhdr; + unsigned char *ip_hdr = (unsigned char *)a_packet; + unsigned char protocol; + unsigned short ip_id; + unsigned short tu_checksum; + + if(NULL == a_packet){ + return "NULL"; + } + + if(flwd_cfg_val.flwd_log_level <= 10){ + if(0x40 == (ip_hdr[0] & 0xF0)){ /* sappIPͷ, Իȡraw_pkt, ߿IPͷһIPV4IPV6 */ + ipv4_hdr = (flwd_ipv4_hdr_t *)a_packet; + protocol = ipv4_hdr->ip_p; + ip_id = ntohs(ipv4_hdr->ip_id); + }else{ + ipv6_hdr = (flwd_ipv6_hdr_t *)a_packet; + protocol = ipv6_hdr->ip6_nxt_hdr; + ip_id = 0; + } + + inet_ntop(AF_INET, &ipv4_hdr->ip_src.s_addr, debug_ip_src_str, 64); + inet_ntop(AF_INET, &ipv4_hdr->ip_dst.s_addr, debug_ip_dst_str, 64); + if(6 == protocol){ + thdr = (flwd_tcp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(thdr->th_sport); + debug_dport = ntohs(thdr->th_dport); + tu_checksum = ntohs(thdr->th_sum); + }else if (17 == protocol){ + uhdr = (flwd_udp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(uhdr->uh_sport); + debug_dport = ntohs(uhdr->uh_dport); + tu_checksum = ntohs(uhdr->uh_sum); + }else{ + debug_sport = 0; + debug_dport = 0; + } + } + + snprintf(buf, buf_max_len, "%s,%u ---> %s,%u, pro:%u, ipid:0x%04x, checksum:0x%04x", + debug_ip_src_str, debug_sport, debug_ip_dst_str, debug_dport, + protocol, + ip_id, + tu_checksum); + + return buf; +} + + +const char *flwd_debug_print_tuple4_r(const void *a_packet, char *buf, int buf_max_len) +{ + char debug_ip_src_str[64], debug_ip_dst_str[64]; + unsigned short debug_sport, debug_dport; + const flwd_ipv4_hdr_t *ipv4_hdr; + const flwd_ipv6_hdr_t *ipv6_hdr; + const flwd_tcp_hdr_t *thdr; + const flwd_udp_hdr_t *uhdr; + unsigned char *ip_hdr = (unsigned char *)a_packet; + unsigned char protocol; + + if(flwd_cfg_val.flwd_log_level <= 10){ + if(0x40 == (ip_hdr[0] & 0xF0)){ /* һIPV4IPV6 */ + ipv4_hdr = (flwd_ipv4_hdr_t *)a_packet; + protocol = ipv4_hdr->ip_p; + }else{ + ipv6_hdr = (flwd_ipv6_hdr_t *)a_packet; + protocol = ipv6_hdr->ip6_nxt_hdr; + } + + inet_ntop(AF_INET, &ipv4_hdr->ip_src.s_addr, debug_ip_src_str, 64); + inet_ntop(AF_INET, &ipv4_hdr->ip_dst.s_addr, debug_ip_dst_str, 64); + if(6 == protocol){ + thdr = (flwd_tcp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(thdr->th_sport); + debug_dport = ntohs(thdr->th_dport); + }else if (17 == protocol){ + uhdr = (flwd_udp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(uhdr->uh_sport); + debug_dport = ntohs(uhdr->uh_dport); + }else{ + debug_sport = 0; + debug_dport = 0; + } + } + + snprintf(buf, buf_max_len, "%s,%u ---> %s,%u", debug_ip_src_str, debug_sport, debug_ip_dst_str, debug_dport); + + return buf; +} + + diff --git a/src/common/flwd_compat_marsio_hash.c b/src/common/flwd_compat_marsio_hash.c new file mode 100644 index 0000000..dee143a --- /dev/null +++ b/src/common/flwd_compat_marsio_hash.c @@ -0,0 +1,23 @@ + +#include "flowood.h" +#include "flowood_fun.h" +#include +#include +#include +#include +#include +#include +#include +#include +/* + Ҫ֤İԪ, marsioķ㷨, + ʱֵܱͬһ߳, ֤ҵԭnat_session. +*/ + +unsigned int compat_marsio_tuple4_hash(const flwd_tuple5_t *nat_key) +{ + /* TODO, marsio㷨, ֤ͬԴͬ */ + + return 0; +} + diff --git a/src/common/flwd_network_connect.c b/src/common/flwd_network_connect.c new file mode 100644 index 0000000..e875e87 --- /dev/null +++ b/src/common/flwd_network_connect.c @@ -0,0 +1,363 @@ +#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 +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct{ + char region_str[FLWD_REGION_STR_LEN_MAX]; + unsigned int vlan_id; + unsigned int conn_forward_gateway_array[FLWD_NETWORK_NxM_MAX]; /* תIP, */ + int conn_forward_gateway_array_num; +}flwd_network_gdev_data_t; + +/* + NOTE: + GDEVFWD֮NxMϵ, ͨñ, ֮access, һѡ˵ĻԾIP, ӦýĸFWDͨĸGDEVȥ. + + active_IP: access---->forwad---->gdev---->INTERNET. + + + config: + region vlan gdev_redirect_ip forward_manage_ip forward_feedback_ip + + + region: , ʡ; + vlan : ֹһֵڵGDEVfrowardܲͨ, 񡢿VLANȵ, ʶ; + gdev_redirect_ip: GDEVĻIP + forward_manage_ip: תعIP + forward_feedback_ip: תصݻشIP + + ȫһ, accessзֶ˿ڵ, Ҫȫͬ, ޸!!!! +*/ + + + + + +static int flwd_network_gdev_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_network_gdev_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_network_gdev_data_free(void *data) +{ + assert(0); /* ʱԶfree, Ͳߵ, !!! */ +} + +/* + NOTE: + htablegdev_ipΪkey, + flwd_network_gdev_data_tṹΪdata, + ȥĸgdev, ͨЩforward. +*/ +static MESA_htable_handle flwd_create_network_gdev_table(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; + MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, &opt_int, sizeof(int)); + + opt_int = 1000; + MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, &opt_int, sizeof(int)); + + opt_int = 0; + MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, &opt_int, sizeof(int)); /* ̭ */ + + opt_int = HASH_ELIMINATE_ALGO_FIFO; /* ߳ģʽFIFO */ + MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, &opt_int, sizeof(int)); + + MESA_htable_set_opt(htable, MHO_CBFUN_KEY_COMPARE, (void *)&flwd_network_gdev_key_cmp, sizeof(void *)); + + MESA_htable_set_opt(htable, MHO_CBFUN_KEY_TO_INDEX, (void *)&flwd_network_gdev_key2index, sizeof(void *)); + + MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, (void *)&flwd_network_gdev_data_free, sizeof(void *)); + + opt_int = 0; + 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; +} + +/* + pattern: + #region vlan_id gdev_redirect_ip +*/ +static int flwd_network_gdev_cfg_parse(void) +{ + FILE *fp; + char __raw_line_buf[1024]; + char line_buf[1024]; + const char *delim = "\t "; + char *save_ptr; + flwd_network_gdev_data_t *tmp_data; + char *section, *region_str, *gdev_ip_str; + unsigned int hkey; + int ret; + + fp = fopen("./conf/ip_reuse/network_gdev.cfg", "r"); + if(NULL == fp){ + return -1; + } + + while(fgets(__raw_line_buf, 1024, fp)){ + if('#' ==__raw_line_buf[0]){ + continue; + } + memcpy(line_buf, __raw_line_buf, 1024); + flwd_del_last_rn(line_buf, 1024); + tmp_data = (flwd_network_gdev_data_t *)calloc(1, sizeof(flwd_network_gdev_data_t)); + + /* region */ + section = strtok_r(line_buf, delim, &save_ptr); + if(NULL == section){ + return -1; + } + strncpy(tmp_data->region_str, section, FLWD_REGION_STR_LEN_MAX-1); + region_str = section; + + /* vlan_id */ + section = strtok_r(NULL, delim, &save_ptr); + if(NULL == section){ + return -1; + } + tmp_data->vlan_id = (unsigned int)atoi(section); + + /* gdev_redirect_ip */ + section = strtok_r(NULL, delim, &save_ptr); + if(NULL == section){ + return -1; + } + if(inet_pton(AF_INET, section, &hkey) <= 0){ + return -1; + } + gdev_ip_str = section; + + ret = MESA_htable_add(flwd_global_val.flwd_network_conn_table, (const uchar *)&hkey, sizeof(int), tmp_data); + if(ret >= 0){ + flwd_log(10, "parse network_gdev.cfg, %s\t%u\t%s\n", region_str, tmp_data->vlan_id, gdev_ip_str); + }else{ + flwd_log(30, "parse network_gdev.cfg error, %s\n", __raw_line_buf); + } + + while(strtok_r(NULL, delim, &save_ptr)); + } + + fclose(fp); + + return 0; +} + + +static int flwd_network_gdev_fwd_relate_cb(const uchar * key, uint size, void * data, void * user) +{ + flwd_network_gdev_data_t *hdata = (flwd_network_gdev_data_t *)data; + flwd_network_gdev_data_t *tmp_fwd_data = (flwd_network_gdev_data_t *)user; + + if(strlen(hdata->region_str) != strlen(tmp_fwd_data->region_str)){ + return ITERATE_CB_RET_CONTINUE_FLAG; /* MESA_htable_iterate_bytime޷ػصֵ, øtrick, conn_forward_gateway_array_num=2ҵ, 1 */ + } + + if(strncmp(hdata->region_str, tmp_fwd_data->region_str,strlen(hdata->region_str)) != 0){ + return ITERATE_CB_RET_CONTINUE_FLAG; + } + + if(hdata->vlan_id != tmp_fwd_data->vlan_id){ + return ITERATE_CB_RET_CONTINUE_FLAG; + } + + tmp_fwd_data->conn_forward_gateway_array_num = 2; /* bingo! */ + + if(hdata->conn_forward_gateway_array_num >= FLWD_NETWORK_NxM_MAX){ + assert(0); + } + + hdata->conn_forward_gateway_array[hdata->conn_forward_gateway_array_num] = tmp_fwd_data->conn_forward_gateway_array[0]; + hdata->conn_forward_gateway_array_num++; + + /* NOTE: м!!! ҵһеGDEV, ˴Ҳжcallback, ΪһڻGDEV, Ҫȫһ */ + return ITERATE_CB_RET_CONTINUE_FLAG; +} + +static void flwd_network_gdev_fwd_relate(flwd_network_gdev_data_t *tmp_data) +{ + /* */ + MESA_htable_iterate_bytime(flwd_global_val.flwd_network_conn_table, ITERATE_TYPE_OLDEST_FIRST, + flwd_network_gdev_fwd_relate_cb, tmp_data); + + return ; +} + + +/* + #region vlan_id forward_ip +*/ +static int flwd_network_forward_cfg_parse(void) +{ + FILE *fp; + char line_buf[1024]; + const char *delim = "\t "; + char *save_ptr; + flwd_network_gdev_data_t tmp_data; + char *section; + char *forward_ip; + + fp = fopen("./conf/ip_reuse/network_forward.cfg", "r"); + if(NULL == fp){ + return -1; + } + + while(fgets(line_buf, 1024, fp)){ + if('#' ==line_buf[0]){ + continue; + } + flwd_del_last_rn(line_buf, 1024); + memset(&tmp_data, 0, sizeof(flwd_network_gdev_data_t)); + + section = strtok_r(line_buf, delim, &save_ptr); + if(NULL == section){ + return -1; + } + strncpy(tmp_data.region_str, section, FLWD_REGION_STR_LEN_MAX-1); + + section = strtok_r(NULL, delim, &save_ptr); + if(NULL == section){ + return -1; + } + tmp_data.vlan_id = (unsigned int)atoi(section); + + section = strtok_r(NULL, delim, &save_ptr); + if(NULL == section){ + return -1; + } + if(inet_pton(AF_INET, section, &tmp_data.conn_forward_gateway_array[0]) <= 0){ /* һ0, ʱ洢 forward_ip */ + return -1; + } + forward_ip = section; + tmp_data.conn_forward_gateway_array_num = 1; + + flwd_network_gdev_fwd_relate(&tmp_data); + /* MESA_htable_iterate_bytime޷ػصֵ, øtrick, conn_forward_gateway_array_num=2ҵ, 1 */ + if(2 != tmp_data.conn_forward_gateway_array_num){ + flwd_log(30, "can't found related gdev ip in network_gdev.cfg, network_forward.cfg->forward ip:%s\n", forward_ip); + return -1; + }else{ + flwd_log(10, "parse network_gdev.cfg->%s\n", forward_ip); + } + + while(strtok_r(NULL, delim, &save_ptr)); + } + + fclose(fp); + + return 0; +} + +/* TODO, + + ///ѡĻԾIPڵGDEV_IPID, , ȷӦôĸFWD + + һֵ˵, ظһת, ͨеINLINE-DEVICE, + + IPַ. + +*/ +unsigned int flwd_search_fwd_ip_by_gdev_ip(unsigned int gdev_ip_net_order) +{ + flwd_network_gdev_data_t *hdata; + char ip_str[16]; + int rnd_num; + + hdata = (flwd_network_gdev_data_t *)MESA_htable_search(flwd_global_val.flwd_network_conn_table, (unsigned char *)&gdev_ip_net_order, sizeof(int)); + if(NULL == hdata){ + inet_ntop(AF_INET, &gdev_ip_net_order, ip_str, 16); + flwd_log(30, "not found gdev ip %s in network_gdev.cfg\n", ip_str); + return -1; + } + + /* NxM˹ϵ, , ѡһת */ + rnd_num = rand() % hdata->conn_forward_gateway_array_num; + + return hdata->conn_forward_gateway_array[rnd_num]; + /* + TODO: + дһgdev_ipFWDݿIPľ̬, + + ߿һrip·Э, Զ㲥, Զ. + + ʱֶд, ʵʾ10.0.6.201em1IPַ: 172.16.1.201. + */ + + //inet_pton(AF_INET, "10.0.6.201", &gdev_ip_net_order); + //inet_pton(AF_INET, "172.16.1.201", &gdev_ip_net_order); + //inet_pton(AF_INET, "47.74.128.220", &gdev_ip_net_order); + //return gdev_ip_net_order; +} + +int flwd_network_conn_init(void) +{ + flwd_global_val.flwd_network_conn_table = flwd_create_network_gdev_table(); + + /* NOTE, ȵflwd_network_gdev_cfg_parse, ӵhtable, ٵflwd_network_forward_cfg_parse */ + if(flwd_network_gdev_cfg_parse() < 0){ + flwd_log(30, "flwd_network_gdev_cfg_parse error!\n"); + return -1; + } + + /* NOTE, ȵflwd_network_gdev_cfg_parse, ӵhtable, ٵflwd_network_forward_cfg_parse */ + if(flwd_network_forward_cfg_parse() < 0){ + flwd_log(30, "flwd_network_forward_cfg_parse error!\n"); + return -1; + } + return 0; +} + + diff --git a/src/common/flwd_sendpacket.c b/src/common/flwd_sendpacket.c new file mode 100644 index 0000000..701a447 --- /dev/null +++ b/src/common/flwd_sendpacket.c @@ -0,0 +1,138 @@ + +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_handle_logger.h" +#include +#include +#include +#include +#include +#include +#include + +int flwd_sendpacket_build_ethernet(u_int16_t eth_type_host_order, + const unsigned char *src_mac, const unsigned char *dst_mac, char *buf) +{ + flwd_eth_hdr_t *snd_eth_hdr = (flwd_eth_hdr_t *)buf; + + memcpy(snd_eth_hdr->h_dest, dst_mac, ETH_ALEN); + memcpy(snd_eth_hdr->h_source, src_mac, ETH_ALEN); + + snd_eth_hdr->h_proto = htons(eth_type_host_order); + + return 0; +} + + +int flwd_sendpacket_build_arp(u_short hrd_host, u_short pro_host, + u_char hln, u_char pln, u_short op_host, u_char *sha, u_char *spa, + u_char *tha, u_char *tpa, char *buf) +{ + flwd_arp_hdr_t *arp_hdr = (flwd_arp_hdr_t *)buf; + + if (!buf){ + return (-1); + } + + arp_hdr->ar_hrd = htons(hrd_host); /* hardware address type */ + arp_hdr->ar_pro = htons(pro_host); /* protocol address type */ + arp_hdr->ar_hln = hln; /* hardware address length */ + arp_hdr->ar_pln = pln; /* protocol address length */ + arp_hdr->ar_op = htons(op_host); /* opcode command */ + memcpy(arp_hdr->ar_sha, sha, hln); /* sender hardware address */ + memcpy(arp_hdr->ar_spa, spa, pln); /* sender protocol (IP) address */ + memcpy(arp_hdr->ar_tha, tha, hln); /* target hardware address */ + memcpy(arp_hdr->ar_tpa, tpa, pln); /* target protocol (IP) address */ + + return (0); +} + +int flwd_sendpacket_build_ipv4(u_int16_t carry_layer_len, u_int8_t tos, + u_int16_t id, u_int16_t frag, u_int8_t ttl, u_int8_t prot, u_int32_t src_net_order, + u_int32_t dst_net_order, const char *payload, int payload_s, char *buf) +{ + flwd_ipv4_hdr_t *ip_hdr; + + if (!buf){ + return (-1); + } + + ip_hdr = (flwd_ipv4_hdr_t *)buf; + + ip_hdr->ip_v = 4; /* version 4 */ + ip_hdr->ip_hl = 5; /* 20 byte header */ + ip_hdr->ip_tos = tos; /* IP tos */ + ip_hdr->ip_len = htons(sizeof(flwd_ipv4_hdr_t) + carry_layer_len); /* total length */ + ip_hdr->ip_id = htons(id); /* IP ID */ + ip_hdr->ip_off = htons(frag); /* fragmentation flags */ + ip_hdr->ip_ttl = ttl; /* time to live */ + ip_hdr->ip_p = prot; /* transport protocol */ + ip_hdr->ip_sum = 0; /* do this later */ + ip_hdr->ip_src.s_addr = src_net_order; + ip_hdr->ip_dst.s_addr = dst_net_order; + if (payload && payload_s){ + /* + * Unchecked runtime error for buf + IP_H + payload to be greater than + * the allocated heap memory. + */ + memcpy(buf + sizeof(flwd_ipv4_hdr_t), payload, payload_s); + } + + return (0); +} + + +/* ڹ: ICMP-ECHO-REQUEST, ICMP-ECHO-REPLAY */ +int flwd_sendpacket_build_icmpv4_echo(u_int8_t type, u_int8_t code, + u_int16_t sum, u_int16_t id_net_order, u_int16_t seq_net_order, char *payload, + u_int32_t payload_s, char *buf) +{ + flwd_simple_icmp_hdr_t *icmp_hdr = (flwd_simple_icmp_hdr_t *)buf; + + icmp_hdr->icmp_type = type; + icmp_hdr->icmp_code = code; + icmp_hdr->icmp_cksum = 0; /* checksum done in userland */ + icmp_hdr->icd_id = id_net_order; + icmp_hdr->icd_seq = seq_net_order; + + if(payload && payload_s){ + /* + * Unchecked runtime error for buf + IP_H + payload to be greater than + * the allocated heap memory. + */ + memcpy(buf + sizeof(flwd_simple_icmp_hdr_t), payload, payload_s); + } + + return 0; +} + +int flwd_sendpacket_build_udp(u_int16_t carry_layer_len, + u_int16_t sport_net_order, u_int16_t dport_net_order, + const char *payload, int payload_s, char *buf) +{ + flwd_udp_hdr_t udp_hdr; + + if (!buf) + { + return (-1); + } + + udp_hdr.uh_sport = sport_net_order; /* source port */ + udp_hdr.uh_dport = dport_net_order; /* destination port */ + udp_hdr.uh_ulen = htons(sizeof(flwd_udp_hdr_t) + carry_layer_len); /* total length */ + udp_hdr.uh_sum = 0; /* checksum */ + + if (payload && payload_s) + { + /* + * Unchecked runtime error for buf + UDP_H + payload to be greater + * than the allocated heap memory. + */ + memcpy(buf + sizeof(flwd_udp_hdr_t), payload, payload_s); + } + memcpy(buf, &udp_hdr, sizeof(udp_hdr)); + return (1); +} + + diff --git a/src/common/flwd_status.c b/src/common/flwd_status.c new file mode 100644 index 0000000..fe01d2b --- /dev/null +++ b/src/common/flwd_status.c @@ -0,0 +1,275 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include +#include +#include +#include + +static unsigned long TO_KB = 1024; +static unsigned long TO_MB = 1024 * 1024; +static unsigned long TO_GB = 1024 * 1024 * 1024UL; +static unsigned long TO_TB; + +/* ת׶ַ, 123bps, 34.5Mbps, һ */ +static char *byte_convert_to_human(unsigned long long bytes, int interval, int multiple, char * byte_str) +{ + if(0 == bytes){ + return (char *)"0"; + } + bytes *= multiple; /* to network pattern, or human pattern */ + + bytes /= interval; /* per second */ + + if(bytes < TO_KB){ + snprintf(byte_str,TRAFFIC_STAT_STR_LEN,"%llu", bytes); + }else if(bytes < TO_MB){ + snprintf(byte_str,TRAFFIC_STAT_STR_LEN,"%.2fK", (float)bytes/TO_KB); + }else if(bytes < TO_GB){ + snprintf(byte_str,TRAFFIC_STAT_STR_LEN,"%.2fM", (float)bytes/TO_MB); + }else if(bytes < TO_TB){ + snprintf(byte_str,TRAFFIC_STAT_STR_LEN,"%.2fG", (float)bytes/TO_GB); + }else{ + snprintf(byte_str,TRAFFIC_STAT_STR_LEN,"%.2fT", (double)bytes/TO_TB); + } + + return byte_str; +} + + +static void flwd_show_stream_stat(FILE *fp) +{ + unsigned long long tot_stream_num = 0; + int i; + + for(i = 0; i < FLWD_MAX_THREAD_NUM; i++){ + if(flwd_thread_val[i].nat_info_table != NULL){ + tot_stream_num += MESA_htable_get_elem_num(flwd_thread_val[i].nat_info_table); + } + } + + fprintf(fp,"Total stream number is:%llu\n", tot_stream_num); + + return; +} + +static void flwd_pkt_flow_stat(FILE *fp) +{ + int tseq; + char human_byte_str[TRAFFIC_STAT_STR_LEN], human_bps_str[TRAFFIC_STAT_STR_LEN]; + + static unsigned long long history_eth_pkt_sum = 0, history_ip_pkt_sum = 0, history_tcp_pkt_sum = 0, history_udp_pkt_sum = 0; + static unsigned long long history_eth_byte_sum = 0, history_ip_byte_sum = 0, history_tcp_byte_sum = 0, history_udp_byte_sum = 0; + unsigned long long eth_pkt_sum = 0, ip_pkt_sum = 0, tcp_pkt_sum = 0, udp_pkt_sum = 0; + unsigned long long eth_byte_sum = 0, ip_byte_sum = 0, tcp_byte_sum = 0, udp_byte_sum = 0; + + for(tseq = 0; tseq < flwd_cfg_val.tot_thread_count; tseq++){ + eth_pkt_sum += flwd_thread_val[tseq].pkt_stat.eth_pkt_num; + ip_pkt_sum += flwd_thread_val[tseq].pkt_stat.ip_pkt_num; + tcp_pkt_sum += flwd_thread_val[tseq].pkt_stat.tcp_pkt_num; + udp_pkt_sum += flwd_thread_val[tseq].pkt_stat.udp_pkt_num; + + eth_byte_sum += flwd_thread_val[tseq].pkt_stat.eth_pkt_byte; + ip_byte_sum += flwd_thread_val[tseq].pkt_stat.ip_pkt_byte; + tcp_byte_sum += flwd_thread_val[tseq].pkt_stat.tcp_pkt_byte; + udp_byte_sum += flwd_thread_val[tseq].pkt_stat.udp_pkt_byte; + } + + fprintf(fp,"%-10s %12s %12s %12s %12s\n","PKT-TYPE", "total_pkt", "total_len","pps", "bps"); + fprintf(fp,"%-10s %12llu %12s %12llu %12s\n", "Ethernet", eth_pkt_sum, byte_convert_to_human(eth_byte_sum, 1, 1, human_byte_str), eth_pkt_sum-history_eth_pkt_sum, byte_convert_to_human(eth_byte_sum-history_eth_byte_sum, 1, 8, human_bps_str)); + fprintf(fp,"%-10s %12llu %12s %12llu %12s\n", "IPv4", ip_pkt_sum, byte_convert_to_human(ip_byte_sum, 1, 1, human_byte_str), ip_pkt_sum-history_ip_pkt_sum, byte_convert_to_human(ip_byte_sum-history_ip_byte_sum, 1, 8, human_bps_str)); + fprintf(fp,"%-10s %12llu %12s %12llu %12s\n", "TCP", tcp_pkt_sum, byte_convert_to_human(tcp_byte_sum, 1, 1, human_byte_str), history_tcp_pkt_sum-history_tcp_pkt_sum, byte_convert_to_human(tcp_byte_sum-history_tcp_byte_sum, 1, 8, human_bps_str)); + fprintf(fp,"%-10s %12llu %12s %12llu %12s\n", "UDP", udp_pkt_sum, byte_convert_to_human(udp_byte_sum, 1, 1, human_byte_str), udp_pkt_sum-history_udp_pkt_sum, byte_convert_to_human(udp_byte_sum-history_udp_byte_sum, 1, 8, human_bps_str)); + + history_eth_pkt_sum = eth_pkt_sum; + history_ip_pkt_sum = ip_pkt_sum; + history_tcp_pkt_sum = tcp_pkt_sum; + history_udp_pkt_sum = udp_pkt_sum; + + history_eth_byte_sum = eth_byte_sum; + history_ip_byte_sum = ip_byte_sum; + history_tcp_byte_sum = tcp_byte_sum; + history_udp_byte_sum = udp_byte_sum; + + flwd_show_stream_stat(fp); + +} + +typedef struct{ + unsigned long long tot_ip_pool_num; /* ν, Э޹ */ + unsigned long long usable_ip_pool_tcp_num; /* IPҪTCP, UDP */ + unsigned long long usable_ip_pool_udp_num; /* IPҪTCP, UDP */ +}flwd_ip_pool_num_stat_t; + +typedef struct{ + FILE *detail_log_fp; /* Ϊ, static, dynamicΪļ */ + flwd_active_ip_type_t act_ip_type; /* static, dynamic */ + int this_callback_location; /* inland, outland */ + flwd_ip_pool_num_stat_t ip_pool_num[2]; +}flwd_ip_pool_log_stat_t; + + +static flwd_ip_pool_log_stat_t static_ip_pool_log_info; /* 0:inland; 1:outland */ +static flwd_ip_pool_log_stat_t dynamic_ip_pool_log_info; /* 0:inland; 1:outland */ + +static int flwd_ip_pool_num_stat_cb(const uchar * key, uint size, void * data, void * user) +{ + flwd_active_ip_t *act_ip_list_head = (flwd_active_ip_t *)data; + flwd_active_ip_t *tmp_ip; + MESA_list_t *list_node; + flwd_ip_pool_log_stat_t *st_ip_pool_log_info = (flwd_ip_pool_log_stat_t *)user; + char ip_str[64]; + long usable_ip_tcpport_num, usable_ip_udpport_num; + + if((FLWD_ACT_IP_STATIC == act_ip_list_head->ip_origin_type) && (strncmp((const char*)"GPID", (const char*)key, 4) != 0)){ + /* NOTE: htableлһipΪkey, Ϊö˿ڻʱҵӦIPڵ, hnodeGPIDxxxΪkeyһ, ־дظ, */ + return ITERATE_CB_RET_CONTINUE_FLAG; + } + + list_node = &act_ip_list_head->active_ip_list_node; /* dynamicstaticһ, һڵact_ip_list_headʼ */ + + do{ + tmp_ip = (flwd_active_ip_t *)list_node->quiddity; + st_ip_pool_log_info->ip_pool_num[st_ip_pool_log_info->this_callback_location].tot_ip_pool_num++; + usable_ip_tcpport_num = MESA_list_count_get_count(&tmp_ip->usable_tcp_sport_list_head); + if(usable_ip_tcpport_num > 0){ + st_ip_pool_log_info->ip_pool_num[st_ip_pool_log_info->this_callback_location].usable_ip_pool_tcp_num++; + } + + usable_ip_udpport_num = MESA_list_count_get_count(&tmp_ip->usable_udp_sport_list_head); + if(usable_ip_udpport_num > 0){ + st_ip_pool_log_info->ip_pool_num[st_ip_pool_log_info->this_callback_location].usable_ip_pool_udp_num++; + } + if(NULL != st_ip_pool_log_info->detail_log_fp){ + flwd_ipt_ntop_r(&tmp_ip->active_ip_net_order, ip_str, 64); + fprintf(st_ip_pool_log_info->detail_log_fp, "%s, %s ---> TCP: %6d, %6ld\n", + flwd_ip_region_ntop(st_ip_pool_log_info->this_callback_location), + ip_str, + (int)flwd_act_ip_get_usable_tcp_sport_num(), + usable_ip_tcpport_num); + fprintf(st_ip_pool_log_info->detail_log_fp, "%s, %s ---> UDP: %6d, %6ld\n", + flwd_ip_region_ntop(st_ip_pool_log_info->this_callback_location), + ip_str, + (int)flwd_act_ip_get_usable_udp_sport_num(), + usable_ip_udpport_num); + } + + list_node = list_node->nextele; + }while(list_node != &act_ip_list_head->active_ip_list_node); + + return ITERATE_CB_RET_CONTINUE_FLAG; +} + +static void flwd_ip_pool_num_stat(void *htable, flwd_ip_pool_log_stat_t *st_ip_pool_log_info) +{ + MESA_htable_iterate_bytime(htable, ITERATE_TYPE_NEWEST_FIRST, flwd_ip_pool_num_stat_cb, (void *)st_ip_pool_log_info); +} + +static void flwd_log_module_delimiter(FILE *fp_flwd_stat) +{ + fprintf(fp_flwd_stat, "--------------------------------------------------------------\n"); +} + +static void flwd_ip_pool_stat(FILE *fp_flwd_stat) +{ + int tseq; + int v4_or_v6; + + memset(&static_ip_pool_log_info, 0, sizeof(static_ip_pool_log_info)); + memset(&dynamic_ip_pool_log_info, 0, sizeof(dynamic_ip_pool_log_info)); + + static_ip_pool_log_info.detail_log_fp = fopen("./log/static_ip_pool_detail.log", "w+"); + if(static_ip_pool_log_info.detail_log_fp){ + fprintf(static_ip_pool_log_info.detail_log_fp, "#location, ip_pool_addr --> protocol, total_port_num, usable_port_num\n"); + } + + dynamic_ip_pool_log_info.detail_log_fp = fopen("./log/dynamic_ip_pool_detail.log", "w+"); + if(dynamic_ip_pool_log_info.detail_log_fp){ + fprintf(dynamic_ip_pool_log_info.detail_log_fp, "##location, ip_pool_addr --> protocol, total_port_num, usable_port_num\n"); + } + + for(tseq = 0; tseq < flwd_cfg_val.tot_thread_count; tseq++){ + /****** dynamic ****/ + pthread_rwlock_rdlock(&flwd_thread_val[tseq].flwd_ip_pool_dynamic_rwlock); + dynamic_ip_pool_log_info.act_ip_type = FLWD_ACT_IP_DYNAMIC; + for(v4_or_v6 = 0; v4_or_v6 < 2; v4_or_v6++){ + dynamic_ip_pool_log_info.this_callback_location = 0; + flwd_ip_pool_num_stat(flwd_thread_val[tseq].flwd_ip_pool_dynamic_htable[v4_or_v6][0], &dynamic_ip_pool_log_info); + + dynamic_ip_pool_log_info.this_callback_location = 1; + flwd_ip_pool_num_stat(flwd_thread_val[tseq].flwd_ip_pool_dynamic_htable[v4_or_v6][1], &dynamic_ip_pool_log_info); + + } + pthread_rwlock_unlock(&flwd_thread_val[tseq].flwd_ip_pool_dynamic_rwlock); + + /****** static ****/ + pthread_rwlock_rdlock(&flwd_thread_val[tseq].flwd_ip_pool_static_rwlock); + static_ip_pool_log_info.act_ip_type = FLWD_ACT_IP_STATIC; + for(v4_or_v6 = 0; v4_or_v6 < 2; v4_or_v6++){ + static_ip_pool_log_info.this_callback_location = 0; + flwd_ip_pool_num_stat(flwd_thread_val[tseq].flwd_ip_pool_static_htable[v4_or_v6][0], &static_ip_pool_log_info); + + static_ip_pool_log_info.this_callback_location = 1; + flwd_ip_pool_num_stat(flwd_thread_val[tseq].flwd_ip_pool_static_htable[v4_or_v6][1], &static_ip_pool_log_info); + } + pthread_rwlock_unlock(&flwd_thread_val[tseq].flwd_ip_pool_static_rwlock); + } + + fprintf(fp_flwd_stat, "static_ip_pool_num:\n"); + fprintf(fp_flwd_stat, "\tinland\n"); + fprintf(fp_flwd_stat, "\t\ttotal \t: %llu\n", static_ip_pool_log_info.ip_pool_num[0].tot_ip_pool_num); + fprintf(fp_flwd_stat, "\t\tusable\t: TCP:%llu \tUDP:%llu\n", static_ip_pool_log_info.ip_pool_num[0].usable_ip_pool_tcp_num, static_ip_pool_log_info.ip_pool_num[0].usable_ip_pool_udp_num); + + fprintf(fp_flwd_stat, "\toutland\n"); + fprintf(fp_flwd_stat, "\t\ttotal \t: %llu\n", static_ip_pool_log_info.ip_pool_num[1].tot_ip_pool_num); + fprintf(fp_flwd_stat, "\t\tusable\t: TCP:%llu \tUDP:%llu\n", static_ip_pool_log_info.ip_pool_num[1].usable_ip_pool_tcp_num, static_ip_pool_log_info.ip_pool_num[1].usable_ip_pool_udp_num); + + + fprintf(fp_flwd_stat, "dynamic_ip_pool_num:\n"); + fprintf(fp_flwd_stat, "\tinland\n"); + fprintf(fp_flwd_stat, "\t\ttotal \t: %llu\n", dynamic_ip_pool_log_info.ip_pool_num[0].tot_ip_pool_num); + fprintf(fp_flwd_stat, "\t\tusable\t: TCP:%llu \tUDP:%llu\n", dynamic_ip_pool_log_info.ip_pool_num[0].usable_ip_pool_tcp_num, dynamic_ip_pool_log_info.ip_pool_num[0].usable_ip_pool_udp_num); + + fclose(static_ip_pool_log_info.detail_log_fp); + fclose(dynamic_ip_pool_log_info.detail_log_fp); + +} + +void *flwd_stat_thread(void *arg) +{ + time_t last_time = 0; + struct timeval cur_time_val; + FILE *fp_flwd_stat; + + TO_GB = 1024 * 1024 * 1024UL; + TO_TB = (unsigned long long)1024 * 1024 * 1024 * 1024UL; + + while(1){ + gettimeofday(&cur_time_val, NULL); + flwd_global_val.cur_time = cur_time_val.tv_sec; + flwd_global_val.cur_time_usec = cur_time_val.tv_sec * 1000000 + cur_time_val.tv_usec; + + if(last_time < flwd_global_val.cur_time){ + /* NOTE: ܶ಻ͬģҪͬʱдflwd_stat.log, ļ */ + fp_flwd_stat = fopen("./log/flwd_stat.log", "w+"); + if(NULL == fp_flwd_stat){ + printf("Can't open file:%s, %s\n", "./log/flwd_stat.log", strerror(errno)); + continue; + } + + flwd_pkt_flow_stat(fp_flwd_stat); + flwd_log_module_delimiter(fp_flwd_stat); + flwd_ip_pool_stat(fp_flwd_stat); + + last_time = flwd_global_val.cur_time; + + fclose(fp_flwd_stat); + } + + usleep(50); + } + + return NULL; +} + + diff --git a/src/common/linux_jhash_algo.c b/src/common/linux_jhash_algo.c new file mode 100644 index 0000000..31fa7ec --- /dev/null +++ b/src/common/linux_jhash_algo.c @@ -0,0 +1,267 @@ + +/* jhash.h: Jenkins hash support. + * + * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net) + * + * http://burtleburtle.net/bob/hash/ + * + * These are the credits from Bob's sources: + * + * lookup3.c, by Bob Jenkins, May 2006, Public Domain. + * + * These are functions for producing 32-bit hashes for hash table lookup. + * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() + * are externally useful functions. Routines to test the hash are included + * if SELF_TEST is defined. You can use this free for any purpose. It's in + * the public domain. It has no warranty. + * + * Copyright (C) 2009-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu) + * + * I've modified Bob's hash to be useful in the Linux kernel, and + * any bugs present are my fault. + * Jozsef + */ + +#include "flowood.h" + +/* An arbitrary initial parameter */ +#define JHASH_INITVAL (0x20180601) /* flowoodĿ */ + + +#ifndef u32 +typedef unsigned int u32; +#endif + +#ifndef __u32 +typedef unsigned int __u32; +#endif + +/* Best hash sizes are of power of two */ +#define jhash_size(n) ((u32)1<<(n)) +/* Mask the hash value, i.e (value & jhash_mask(n)) instead of (value % n) */ +#define jhash_mask(n) (jhash_size(n)-1) + + +/** + * rol32 - rotate a 32-bit value left + * @word: value to rotate + * @shift: bits to roll + */ +static inline __u32 rol32(__u32 word, unsigned int shift) +{ + return (word << shift) | (word >> (32 - shift)); +} + +/* __jhash_mix -- mix 3 32-bit values reversibly. */ +#define __jhash_mix(a, b, c) \ +{ \ + a -= c; a ^= rol32(c, 4); c += b; \ + b -= a; b ^= rol32(a, 6); a += c; \ + c -= b; c ^= rol32(b, 8); b += a; \ + a -= c; a ^= rol32(c, 16); c += b; \ + b -= a; b ^= rol32(a, 19); a += c; \ + c -= b; c ^= rol32(b, 4); b += a; \ +} + +/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */ +#define __jhash_final(a, b, c) \ +{ \ + c ^= b; c -= rol32(b, 14); \ + a ^= c; a -= rol32(c, 11); \ + b ^= a; b -= rol32(a, 25); \ + c ^= b; c -= rol32(b, 16); \ + a ^= c; a -= rol32(c, 4); \ + b ^= a; b -= rol32(a, 14); \ + c ^= b; c -= rol32(b, 24); \ +} + +#if 0 +/* jhash - hash an arbitrary key + * @k: sequence of bytes as key + * @length: the length of the key + * @initval: the previous hash, or an arbitray value + * + * The generic version, hashes an arbitrary sequence of bytes. + * No alignment or length assumptions are made about the input key. + * + * Returns the hash value of the key. The result depends on endianness. + */ +static inline u32 jhash(const void *key, u32 length, u32 initval) +{ + u32 a, b, c; + const u8 *k = key; + + /* Set up the internal state */ + a = b = c = JHASH_INITVAL + length + initval; + + /* All but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) { + a += __get_unaligned_cpu32(k); + b += __get_unaligned_cpu32(k + 4); + c += __get_unaligned_cpu32(k + 8); + __jhash_mix(a, b, c); + length -= 12; + k += 12; + } + /* Last block: affect all 32 bits of (c) */ + /* All the case statements fall through */ + switch (length) { + case 12: c += (u32)k[11]<<24; + case 11: c += (u32)k[10]<<16; + case 10: c += (u32)k[9]<<8; + case 9: c += k[8]; + case 8: b += (u32)k[7]<<24; + case 7: b += (u32)k[6]<<16; + case 6: b += (u32)k[5]<<8; + case 5: b += k[4]; + case 4: a += (u32)k[3]<<24; + case 3: a += (u32)k[2]<<16; + case 2: a += (u32)k[1]<<8; + case 1: a += k[0]; + __jhash_final(a, b, c); + case 0: /* Nothing left to add */ + break; + } + + return c; +} +#endif + +/* jhash2 - hash an array of u32's + * @k: the key which must be an array of u32's + * @length: the number of u32's in the key + * @initval: the previous hash, or an arbitray value + * + * Returns the hash value of the key. + */ +static inline u32 jhash2(const u32 *k, u32 length, u32 initval) +{ + u32 a, b, c; + + /* Set up the internal state */ + a = b = c = JHASH_INITVAL + (length<<2) + initval; + + /* Handle most of the key */ + while (length > 3) { + a += k[0]; + b += k[1]; + c += k[2]; + __jhash_mix(a, b, c); + length -= 3; + k += 3; + } + + /* Handle the last 3 u32's: all the case statements fall through */ + switch (length) { + case 3: c += k[2]; + case 2: b += k[1]; + case 1: a += k[0]; + __jhash_final(a, b, c); + case 0: /* Nothing left to add */ + break; + } + + return c; +} + + +/* jhash_3words - hash exactly 3, 2 or 1 word(s) */ +static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) +{ + a += JHASH_INITVAL; + b += JHASH_INITVAL; + c += initval; + + __jhash_final(a, b, c); + + return c; +} + +/* + NATתͼݰָƸһ, sport_with_no_id_hash: + sport_with_no_id_hash=0: ڼԪHASH, + sport_with_no_id_hash=1: ڼݰָ; + + NOTE: + Ԫhashʱ, Ҫdir_reverse, + ΪC2SS2CɵkeyԪʵʶһ, + ѭַΪԴĹ, ֻdir_reverseͬ, + C2SS2Cһ, dir_reverse϶෴. +*/ +unsigned int flwd_tuple5_hash(const flwd_tuple5_t *tuple5, int sport_with_no_id_hash) +{ + unsigned int sip; + unsigned int dip; + unsigned int hash_val = 0; + unsigned short sport; /* ԪHASHʱ, ȫbit; ָϢʱ, ֻsport8bit˿ֵ, id, hash */ + unsigned short dport; + + if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type)){ + sip = tuple5->ippair_v4.sip_net_order; + dip = tuple5->ippair_v4.dip_net_order; + }else{ + sip = tuple5->ippair_v6->sip_net_order.s6_addr32[0]; /* ʹ4ֽ */ + dip = tuple5->ippair_v6->dip_net_order.s6_addr32[0]; /* ʹ4ֽ */ + } + + if(sport_with_no_id_hash){ + sport = ntohs(tuple5->sport_net_order) & FLWD_UDP_SPORT_ACTUAL_PORT_MASK; /* ֻĶ˿ֵ, idhashֶ */ + }else{ + sport = tuple5->sport_net_order; + } + dport = tuple5->dport_net_order; + + hash_val = (unsigned int)sport; + hash_val |= ((unsigned int)dport << 16); + hash_val += JHASH_INITVAL; + + __jhash_final(sip, dip, hash_val); + + return hash_val; +} + + + +unsigned int __flwd_tuple5_hash(const flwd_tuple5_t *tuple5) +{ + unsigned int sip; + unsigned int dip; + unsigned int port_union; + unsigned short sport_no_id_hash; /* ԪHASHʱ, ֻsport8bit˿ֵ, id, hash */ + unsigned short dport; + + if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type)){ + if(0 == tuple5->dir_reverse){ + sip = tuple5->ippair_v4.sip_net_order; + dip = tuple5->ippair_v4.dip_net_order; + sport_no_id_hash = ntohs(tuple5->sport_net_order) & FLWD_UDP_SPORT_ACTUAL_PORT_MASK; /* ֻĶ˿ֵ, idhashֶ */ + dport = tuple5->dport_net_order; + }else{ + sip = tuple5->ippair_v4.dip_net_order; + dip = tuple5->ippair_v4.sip_net_order; + sport_no_id_hash = ntohs(tuple5->dport_net_order) & FLWD_UDP_SPORT_ACTUAL_PORT_MASK; /* ֻĶ˿ֵ, idhashֶ */ + dport = tuple5->sport_net_order; + } + }else{ + if(0 == tuple5->dir_reverse){ + sip = tuple5->ippair_v6->sip_net_order.s6_addr32[0]; /* ʹ4ֽ */ + dip = tuple5->ippair_v6->dip_net_order.s6_addr32[0]; /* ʹ4ֽ */ + sport_no_id_hash = ntohs(tuple5->sport_net_order) & FLWD_UDP_SPORT_ACTUAL_PORT_MASK; + dport = tuple5->dport_net_order; + }else{ + sip = tuple5->ippair_v6->dip_net_order.s6_addr32[0]; /* ʹ4ֽ */ + dip = tuple5->ippair_v6->sip_net_order.s6_addr32[0]; /* ʹ4ֽ */ + sport_no_id_hash = ntohs(tuple5->dport_net_order) & FLWD_UDP_SPORT_ACTUAL_PORT_MASK; + dport = tuple5->sport_net_order; + } + } + + port_union = (unsigned int)sport_no_id_hash; + port_union |= ((unsigned int)dport << 16); + port_union += JHASH_INITVAL; + + __jhash_final(sip, dip, port_union); + + return port_union; +} + diff --git a/src/flowood_main.c b/src/flowood_main.c new file mode 100644 index 0000000..7deb452 --- /dev/null +++ b/src/flowood_main.c @@ -0,0 +1,155 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "MESA_handle_logger.h" +#include "MESA_prof_load.h" +#include +#include +#include +#include +#include +#include + +/* + IPϵͳ, + ģ鿪: flowood, + IPϵͳIJΪԴڳ"ƻľ", flower->wood, ƴճһ: flowood. +*/ + +int flowood_version_VERSION_20181019; + +flwd_global_val_t flwd_global_val; /* ȫֱ */ +flwd_global_cfg_t flwd_cfg_val; /* ò */ +flwd_global_thread_t flwd_thread_val[FLWD_MAX_THREAD_NUM]; + +/* + ֲļ, ֹ, д! +*/ +static int flwd_validity_check(void) +{ + if((sizeof(flwd_global_thread_t) % 64) != 0){ + printf("sizeof(flwd_global_thread_t) size is %u, % 64 is %u\n", sizeof(flwd_global_thread_t) , sizeof(flwd_global_thread_t) % 64); + abort(); + } + + /* NOTE: 껹±, һtrick, 0ʼ, ⶨ, ˾! */ + assert(FLWD_IP_ADDR_TYPE_V4 == 0); + assert(FLWD_IP_ADDR_TYPE_V6 == 1); + + /* NOTE: 껹±, 0ʼ, ⶨ, ˾! */ + assert(FLWD_IP_REGION_INLAND == 0); + assert(FLWD_IP_REGION_OUTLAND == 1); + + assert(flwd_cfg_val.current_access_gateway_id <= flwd_cfg_val.global_access_gateway_num); + + assert(flwd_cfg_val.current_access_gateway_id <= 4); /* ֧4̨, FLWD_SPORT_ACC_ID_MASK */ + + return 0; +} + +static void flwd_run(void) +{ + flwd_log(RLOG_LV_DEBUG, "flowood ready to run......"); + + flwd_packet_io_run(); +} + +static int flwd_init(void) +{ + int i, ret, int_tmp; + int log_level; + pthread_t pid; + + flwd_validity_check(); + + memset((void *)&flwd_global_val.zero_ipv6_addr, 0, sizeof(struct in6_addr)); + memset((void *)&flwd_global_val.zero_mac_addr, 0, 6); + + MESA_load_profile_int_def(FLWD_CONFIG_FILE, "log", "log_level", &flwd_cfg_val.flwd_log_level, 20); + + flwd_global_val.flwd_log_handle = MESA_create_runtime_log_handle("./log/ip_reuse.log", log_level); + flwd_global_val.maat_log_handle = MESA_create_runtime_log_handle("./log/ip_reuse_maat.log", log_level); + + MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "thread_num", &int_tmp, 1); + if(int_tmp < 1 || int_tmp > FLWD_MAX_THREAD_NUM){ + flwd_log(RLOG_LV_FATAL, "conf->thread_num invalid!"); + return -1; + } + flwd_cfg_val.tot_thread_count = int_tmp; + for(i = 0; i < __TOPO_MODE_MAX; i++){ + flwd_global_val.global_io_handle[i].tot_thread_count = int_tmp; + } + + MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "global_access_gateway_num", &flwd_cfg_val.global_access_gateway_num, 1); + MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "current_access_gateway_id", &flwd_cfg_val.current_access_gateway_id, 1); + if(flwd_cfg_val.current_access_gateway_id <= 0 || flwd_cfg_val.current_access_gateway_id > flwd_cfg_val.global_access_gateway_num){ + flwd_log(RLOG_LV_FATAL, "conf->current_access_gateway_id invalid!"); + return -1; + } + + MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "use_static_pool_ip_if_no_dynamic", &flwd_cfg_val.use_static_pool_ip_if_no_dynamic, 0); + MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "use_dynamic_pool_ip_if_no_static", &flwd_cfg_val.use_dynamic_pool_ip_if_no_static, 0); + + ret = flwd_gateway_init(); + if(ret < 0){ + return -1; + } + + ret = flwd_arp_table_init(); + if(ret < 0){ + return -1; + } + + pthread_create(&pid, NULL, flwd_stat_thread, NULL); + + return 0; +} + + +#if FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD +#ifdef __cplusplus +extern "C" { +#endif + +/* תԲʽصsapp */ +int IR_FWD_INIT(void) +{ + int ret; + + ret = flwd_init(); + if(ret < 0){ + return -1; + } + + flwd_log(RLOG_LV_DEBUG, "flwd_init() success!"); + + flwd_run(); + + return 0; +} +#ifdef __cplusplus +} +#endif + +#else +int main(void) +{ + int ret; + + ret = flwd_init(); + if(ret < 0){ + return -1; + } + + flwd_log(RLOG_LV_DEBUG, "flwd_init() success!"); + + flwd_run(); + + while(1){ + pause(); + } + + return 0; +} +#endif + + diff --git a/src/forward/Makefile b/src/forward/Makefile new file mode 100644 index 0000000..99d476c --- /dev/null +++ b/src/forward/Makefile @@ -0,0 +1,27 @@ +#CC=gcc +CC=g++ +CCC=g++ + +TARGET=flowood_forward.o flwd_fwd_idle_call.o + +CFLAGS += -g -Wall -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 +H_DIR += -I/opt/mrzcpd/include + +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/forward/flowood_forward.c b/src/forward/flowood_forward.c new file mode 100644 index 0000000..f422067 --- /dev/null +++ b/src/forward/flowood_forward.c @@ -0,0 +1,1044 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include +#include +#include +#include +#include +#include + +/* + IPϵͳת, sappʽ. + TCPALLUDP, ݲִ֧IPЭ, ICMP, GREIPЭ. + + ͽزͨUDP-SOCKETʽ, ߳շ, + GDEVݽIPREUSE_TCPALL_ENTRY()IPREUSE_UDP_ENTRY(), + ת֮ں:flwd_packet_io_work_thread(). +*/ + + +/* NATԸ, maatص, maat */ +int flowood_forward_nat_strategy_update_cb() +{ + return 0; +} + +void * flwd_fwd_to_gdev_pre_output(flwd_device_handle_t *rcv_device_handle, + flwd_device_handle_t *send_device_handle, int tid, flwd_raw_pkt_t *raw_pkt) +{ + 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; + + unsend_raw_data_ptr += FLWD_VXLAN_OUTER_PACKET_LEN; /* vxlanͷ, ָڲݰmacͷ */ + unsend_raw_data_len -= FLWD_VXLAN_OUTER_PACKET_LEN; + + /* վĻ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(NULL == send_buf_data_ptr){ + send_device_handle->low_level_mbuff_free(send_device_handle, tid, send_mbuff); + return NULL; + } +#if FLWD_NO_GDEV_ENV + /* ûGDEVĻ, ֶmac, marsio, , mrtunnatԶ */ + +#if FLWD_NO_ACTIVE_ARP_QUERY + /* ֹʵʶԶ˷mac */ + unsigned char *local_fwd_gateway_mac = send_device_handle->io_para.local_mac_addr; + ///unsigned char remote_gdev_mac[6] = {0x74, 0x86, 0x7a, 0xd0, 0x25, 0x18}; /* 10.0.6.240 */ + unsigned char remote_gdev_mac[6] = {0xe8, 0x61, 0x1f, 0x13, 0x70, 0x7a}; /* 192.168.10.5 */ + + flwd_sendpacket_build_ethernet(ETH_P_IP, local_fwd_gateway_mac, remote_gdev_mac, send_buf_data_ptr); +#else + /* + ȷĸgdev? + + 1-еתյ, ˻Ծip, ͽactive_ip <---> gdev_ipĶӦϵ洢, maat-redisɢ; + תյصĵһ, ѯϵ, ֪ĸGDEV, + + active_ip˹õ, ĸתضûյ, Ҳûϵ, ⷢһgdev. + + ԴԾipַ, ҵ񵽴ݰgdevip + */ + unsigned char remote_gdev_mac[6]; + flwd_ip_t gdev_ip; + gdev_ip.addr_type = FLWD_IP_ADDR_TYPE_V4; + gdev_ip.addr_ipv4 = send_device_handle->io_para.gateway_ip_net_order; + ret = flwd_arp_table_query(tid, &gdev_ip, send_device_handle, remote_gdev_mac); + if(ret < 0){ + return NULL; + } + + unsigned char *local_fwd_gateway_mac = send_device_handle->io_para.local_mac_addr; + flwd_sendpacket_build_ethernet(ETH_P_IP, local_fwd_gateway_mac, remote_gdev_mac, send_buf_data_ptr); +#endif + +#else + /* marsio vxlan send */ + +#endif + + return send_mbuff; +} + + + +#if FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD /* ֻתҪsappһ */ +#include "stream.h" +#include "mrtunnat.h" +#include "marsio.h" + +extern "C" int MESA_sendpacket_iplayer_options(int thread_index,const char *data, int data_len, u_int8_t dir, SAPP_TLV_T *options, int opt_num); +extern "C" mr_instance *sapp_get_marsio_instance(void); +extern "C" void *packet_io_alias_ref_get(int target_id); +extern "C" int marsio_send_burst_with_options_for_tcpdumpmesa(struct mr_sendpath * sendpath, queue_id_t sid, marsio_buff_t * mbufs[], int nr_mbufs, uint16_t options); +extern "C" int sendpacket_build_ipv4(u_int16_t carry_layer_len, u_int8_t tos, u_int16_t id, u_int16_t frag, + u_int8_t ttl, u_int8_t prot, u_int32_t src, u_int32_t dst, const char *payload, + int payload_s, unsigned char *buf); +extern "C" int sendpacket_do_checksum(unsigned char *buf, int protocol, int len); +static mr_instance *flwd_marsio_handle; + + +/* + ֱӵԭʼͽӿ. +*/ + +int flwd_fwd_to_gdev_in_sapp_raw_marsio_mode( + flwd_device_handle_t *send_device_handle, int tid, flwd_raw_pkt_t *raw_pkt) +{ + const flwd_eth_hdr_t *inner_eth_hdr; + const flwd_vxlan_hdr_t *vxlan_hdr; + + flwd_eth_hdr_t *outer_eth_hdr = (flwd_eth_hdr_t *)raw_pkt->outer_pkt_data; + flwd_ipv4_hdr_t *outer_ip4_hdr; + flwd_udp_hdr_t *outer_udp_hdr; + + inner_eth_hdr = (flwd_eth_hdr_t *)(raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t)); + vxlan_hdr = (flwd_vxlan_hdr_t *)(raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t)); + + + flwd_log(10, "FWD: recv pkt from access gateway, link_id:%d, innser_smac:%02x-%02x-%02x-%02x-%02x-%02x, innser_dmac:%02x-%02x-%02x-%02x-%02x-%02x, inner_tuple4:%s\n", + vxlan_hdr->link_id, + inner_eth_hdr->h_source[0], inner_eth_hdr->h_source[1], inner_eth_hdr->h_source[2], inner_eth_hdr->h_source[3], inner_eth_hdr->h_source[4], inner_eth_hdr->h_source[5], + inner_eth_hdr->h_dest[0], inner_eth_hdr->h_dest[1], inner_eth_hdr->h_dest[2], inner_eth_hdr->h_dest[3], inner_eth_hdr->h_dest[4], inner_eth_hdr->h_dest[5], + flwd_debug_print_tuple4_detail((char *)inner_eth_hdr + sizeof(flwd_eth_hdr_t), tid)); + +#if FLWD_RUN_IN_CEIEC_TEST + unsigned char outer_smac[6] = {0xe4, 0x95, 0x6e, 0x20, 0x0d, 0x0a}; //עҵMAC + unsigned char outer_dmac[6] = {0x00, 0x1e, 0x73, 0x6c, 0xfa, 0x43}; //gdev, vlan_ipMAC +#endif + + outer_eth_hdr->h_proto = htons(ETH_P_IP); + memcpy(outer_eth_hdr->h_source, outer_smac, 6); + memcpy(outer_eth_hdr->h_dest, outer_dmac, 6); + + /* build outer ipv4 header */ + sendpacket_build_ipv4(raw_pkt->outer_pkt_len - sizeof(flwd_eth_hdr_t) - sizeof(flwd_ipv4_hdr_t), + 0, + 0, + 0, + 64, + 17, + 0x0100007F, + 0x0100007F, + NULL, + 0, + (unsigned char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t)); + outer_ip4_hdr = (flwd_ipv4_hdr_t *)(raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t)); + +#if FLWD_RUN_IN_CEIEC_TEST + inet_pton(AF_INET, "192.168.1.10", &outer_ip4_hdr->ip_src.s_addr); + inet_pton(AF_INET, "10.1.1.1", &outer_ip4_hdr->ip_dst.s_addr); +#endif + + sendpacket_do_checksum((unsigned char *)outer_ip4_hdr, IPPROTO_IP, sizeof(flwd_ipv4_hdr_t)); + + /* outer udp header */ + outer_udp_hdr = (flwd_udp_hdr_t *)(raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t)); + outer_udp_hdr->uh_ulen = htons(raw_pkt->outer_pkt_len - sizeof(flwd_eth_hdr_t) - sizeof(flwd_ipv4_hdr_t)); + outer_udp_hdr->uh_dport = htons(4789); +#if FLWD_RUN_IN_CEIEC_TEST + outer_udp_hdr->uh_sport = htons(50705); +#else + outer_udp_hdr->uh_sport = htons(50705); +#endif + outer_udp_hdr->uh_sum = 0; + + +#if FLWD_RUN_IN_CEIEC_TEST + /* vxlan header */ + //unsigned char capture_vxlan_data[8] = {0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00}; /* I2C, -> */ + unsigned char capture_vxlan_data[8] = {0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03, 0x00}; /* C2I, -> */ + memcpy((void *)vxlan_hdr, capture_vxlan_data, 8); +#endif + +///////////////// + int inner_ret; + marsio_buff_t *send_mbuf[1]; + unsigned char *real_buf; + struct mr_tunnat_ctrlzone mr_ctrlzone; + int ret; + + if(NULL == flwd_marsio_handle){ + flwd_marsio_handle = sapp_get_marsio_instance(); + } + + inner_ret = marsio_buff_malloc_global(flwd_marsio_handle, send_mbuf, 1, + MARSIO_SOCKET_ID_ANY, send_device_handle->sapp_send_thread_seq); + if(inner_ret < 0){ + return -1; + } + + real_buf = (unsigned char *)marsio_buff_append(send_mbuf[0], raw_pkt->outer_pkt_len); + outer_eth_hdr = (flwd_eth_hdr_t *)real_buf; + + memcpy(real_buf, raw_pkt->outer_pkt_data, raw_pkt->outer_pkt_len); + outer_eth_hdr->h_proto = ntohs(ETH_P_IP);/* ײΪIPv4 */ + + mr_ctrlzone.action |= TUNNAT_CZ_ACTION_ENCAP_NO_SESSION; + mr_ctrlzone.route_dir = vxlan_hdr->dir; + marsio_buff_ctrlzone_set(send_mbuf[0], 0, &mr_ctrlzone, sizeof(struct mr_tunnat_ctrlzone)); + + struct mr_sendpath *snd_path_handle = (struct mr_sendpath * )packet_io_alias_ref_get(1); /* 0Ϊvxlan_user, 1Ϊԭʼ */ + ret = marsio_send_burst_with_options_for_tcpdumpmesa(snd_path_handle, + send_device_handle->sapp_send_thread_seq, + send_mbuf, 1, MARSIO_SEND_OPT_FAST); + if(flwd_cfg_val.flwd_log_level <= 10){ + char outer_tuple4_str[128]; + flwd_log(10, "FWD: send pkt to gdev, link_id:%d, innser_smac:%02x-%02x-%02x-%02x-%02x-%02x, innser_dmac:%02x-%02x-%02x-%02x-%02x-%02x, inner_tuple4:%s, outer_tuple4:%s,\n", + vxlan_hdr->link_id, + inner_eth_hdr->h_source[0], inner_eth_hdr->h_source[1], inner_eth_hdr->h_source[2], inner_eth_hdr->h_source[3], inner_eth_hdr->h_source[4], inner_eth_hdr->h_source[5], + inner_eth_hdr->h_dest[0], inner_eth_hdr->h_dest[1], inner_eth_hdr->h_dest[2], inner_eth_hdr->h_dest[3], inner_eth_hdr->h_dest[4], inner_eth_hdr->h_dest[5], + flwd_debug_print_tuple4_detail((char *)inner_eth_hdr + sizeof(flwd_eth_hdr_t), tid), + flwd_debug_print_tuple4_detail_r(outer_ip4_hdr, outer_tuple4_str, 128)); + } + return ret; +} + + +int flwd_fwd_to_gdev_in_sapp_vxlan_mode( + flwd_device_handle_t *send_device_handle, int tid, flwd_raw_pkt_t *raw_pkt) +{ + SAPP_TLV_T option[32]; + int option_num = 0; + //int vxlan_link_id = 1; + const flwd_eth_hdr_t *inner_eth_hdr; + const flwd_vxlan_hdr_t *vxlan_hdr; + + inner_eth_hdr = (flwd_eth_hdr_t *)(raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t)); + vxlan_hdr = (flwd_vxlan_hdr_t *)(raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t)); + + unsigned char outer_smac[6] = {0xe4, 0x95, 0x6e, 0x02, 0x0d, 0x0a}; + unsigned char outer_dmac[6] = {0x00, 0x1e, 0x73, 0x6c, 0xfa, 0x43}; + + option[option_num].type = SAPP_SEND_OPT_GDEV_SMAC; + option[option_num].length = 6; + memcpy(option[option_num].array_value, outer_smac, 6); + option_num++;//////// + option[option_num].type = SAPP_SEND_OPT_GDEV_DMAC; + option[option_num].length = 6; + memcpy(option[option_num].array_value, outer_dmac, 6); + option_num++;/////// + + option[option_num].type = SAPP_SEND_OPT_GDEV_SIP; + option[option_num].length = 4; +// option[option_num].int_value = g_wangyan_send_fake_pkt_para.vxlan_sip_net_order; + unsigned int gsip_net_order; + inet_pton(AF_INET, "192.168.1.10", &gsip_net_order); /* TODO, cong/gdev.confȡGDEVıעIP */ + option[option_num].int_value = gsip_net_order; + option_num++;/////// + + option[option_num].type = SAPP_SEND_OPT_GDEV_DIP; + option[option_num].length = 4; + //option[option_num].int_value = g_wangyan_send_fake_pkt_para.vxlan_dip_net_order;; + unsigned int gdip_net_order; + inet_pton(AF_INET, "10.1.1.1", &gdip_net_order); /* TODO, ݻԾIPеDEV_IDõ */ + option[option_num].int_value = gdip_net_order; + option_num++;/////// + + option[option_num].type = SAPP_SEND_OPT_GDEV_UDP_SPORT; + option[option_num].length = 2; +// option[option_num].short_value = ntohs(g_wangyan_send_fake_pkt_para.vxlan_sport_net_order); +#if FLWD_RUN_IN_CEIEC_TEST + option[option_num].short_value = ntohs(50709); /* 12ҵ̶˿ں */ +#else + option[option_num].short_value = ntohs(51664); /* 27ҵ̶˿ں */ +#endif + option_num++;/////// + + option[option_num].type = SAPP_SEND_OPT_GDEV_UDP_DPORT; + option[option_num].length = 2; + option[option_num].short_value = ntohs(4789); + option_num++;/////// + + + option[option_num].type = SAPP_SEND_OPT_VXLAN_VPN_ID; + option[option_num].length = 4; +// option[option_num].int_value = htonl(g_wangyan_send_fake_pkt_para.vxlan_vlan_num); + option[option_num].int_value = 7; /* VPN */ + option_num++;/////// + + option[option_num].type = SAPP_SEND_OPT_VXLAN_LINK_ID; + option[option_num].length = 4; + option[option_num].int_value = vxlan_hdr->link_id; + option_num++;/////// + + option[option_num].type = SAPP_SEND_OPT_VXLAN_LINK_ENCAP_TYPE; + option[option_num].length = 1; + option[option_num].char_value = TUNNAT_TUNNEL_TYPE_ETHER; + option_num++;/////// + + option[option_num].type = SAPP_SEND_OPT_VXLAN_LINK_DIR; + option[option_num].length = 1; + option[option_num].char_value = vxlan_hdr->dir; + option_num++;/////// + + + option[option_num].type = SAPP_SEND_OPT_INNER_SMAC; + option[option_num].length = 6; + memcpy(option[option_num].array_value, inner_eth_hdr->h_source, 6); + option_num++;//////// + option[option_num].type = SAPP_SEND_OPT_INNER_DMAC; + option[option_num].length = 6; + memcpy(option[option_num].array_value, inner_eth_hdr->h_dest, 6); + option_num++;/////// + + + flwd_log(10, "recv pkt from access gateway, link_id:%d, innser_smac:%02x-%02x-%02x-%02x-%02x-%02x, innser_dmac:%02x-%02x-%02x-%02x-%02x-%02x!\n", + vxlan_hdr->link_id, + inner_eth_hdr->h_source[0], inner_eth_hdr->h_source[1], inner_eth_hdr->h_source[2], inner_eth_hdr->h_source[3], inner_eth_hdr->h_source[4], inner_eth_hdr->h_source[5], + inner_eth_hdr->h_dest[0], inner_eth_hdr->h_dest[1], inner_eth_hdr->h_dest[2], inner_eth_hdr->h_dest[3], inner_eth_hdr->h_dest[4], inner_eth_hdr->h_dest[5]); + + if(flwd_cfg_val.flwd_log_level <= 10){ + const flwd_ipv4_hdr_t *inner_ip4_hdr = (flwd_ipv4_hdr_t *)(raw_pkt->inner_pkt_data + sizeof(flwd_eth_hdr_t)); + char ip_src_str[32], ip_dst_str[32]; + inet_ntop(AF_INET, &inner_ip4_hdr->ip_src.s_addr, ip_src_str, 32); + inet_ntop(AF_INET, &inner_ip4_hdr->ip_dst.s_addr, ip_dst_str, 32); + + flwd_log(10, "fwd sendto gdev, inner ip: %s->%s, len:%u, ipid:0x%x, proto:%u\n", + ip_src_str, ip_dst_str, ntohs(inner_ip4_hdr->ip_len), + inner_ip4_hdr->ip_id, inner_ip4_hdr->ip_p); + } + + int ret = MESA_sendpacket_iplayer_options(send_device_handle->sapp_send_thread_seq, + raw_pkt->inner_pkt_data + sizeof(flwd_eth_hdr_t), + raw_pkt->inner_pkt_len - sizeof(flwd_eth_hdr_t), + vxlan_hdr->dir, + option, option_num); + + return ret; +} + +#endif + + +static void * flwd_fwd_to_acc_pre_output(flwd_device_handle_t *rcv_device_handle, + flwd_device_handle_t *send_device_handle, int tid, flwd_raw_pkt_t *raw_pkt) + +{ + flwd_vxlan_hdr_t *outer_vxlan_dr; + int ret; + 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;Ļ, ߲ģʽܲһ, device_handleҲһ, 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 + unsigned char *local_fwd_to_acc_mac = send_device_handle->io_para.local_mac_addr; + unsigned char remote_acc_gateway_mac[6] = {0x74, 0x86, 0x7A, 0xD0, 0x1B, 0x30}; /* 10.0.6.229 */ + flwd_sendpacket_build_ethernet(ETH_P_IP, local_fwd_to_acc_mac, remote_acc_gateway_mac, send_buf_data_ptr); +#else + /* TODO: ڲݰԴ˿, ݶ˿ڷΧ, ȫֽid, ҵصipַ, ҶӦipmacַ */ + if(CAP_MODEL_SOCKET != send_device_handle->io_para.cap_mode){ /* socketģʽײЭջװ, flowoodֻһvxlan */ + unsigned char acc_gateway_mac[6]; + flwd_ip_t acc_gateway_ip; + acc_gateway_ip.addr_type = FLWD_IP_ADDR_TYPE_V4; + acc_gateway_ip.addr_ipv4 = send_device_handle->io_para.gateway_ip_net_order; + ret = flwd_arp_table_query(tid, &acc_gateway_ip, send_device_handle, acc_gateway_mac); + if(ret < 0){ + return NULL; + } + } +#endif + + /* NOTE, ʹsocketģʽ, Ҫײvxlanԭʼ, DIP, PORTܶһ, ЩֵǷװݰ, dl_io_sendӰȡ */ +#if FLWD_NO_GDEV_ENV + unsigned int local_fwd_gateway_ip = send_device_handle->io_para.device_ip_net_order; + unsigned int remote_acc_gateway_ip; +// inet_pton(AF_INET, "172.16.1.229", &remote_acc_gateway_ip); +// inet_pton(AF_INET, "10.0.6.229", &remote_acc_gateway_ip); + inet_pton(AF_INET, "202.43.148.188", &remote_acc_gateway_ip); + 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, + local_fwd_gateway_ip, + remote_acc_gateway_ip, + NULL, + 0, + (char *)send_buf_data_ptr + sizeof(flwd_eth_hdr_t)); +#else + abort(); +#endif + + flwd_sendpacket_build_udp(unsend_raw_data_len + sizeof(flwd_vxlan_hdr_t), + htons(50704), /* TODO, ˴sportڲsport, ڲsportȫʶijص, vxlansport */ + htons(64789), + 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ģʽײЭջװ, flowoodֻһvxlan */ + + /* У */ + flwd_sendpacket_do_checksum((char *)send_buf_data_ptr + sizeof(flwd_eth_hdr_t), + IPPROTO_IP, + sizeof(flwd_ipv4_hdr_t)); + } + + /* TODO, vxlanݰЭջ, ȲУ */ + outer_vxlan_dr = (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_dr, 0, sizeof(flwd_vxlan_hdr_t)); + outer_vxlan_dr->link_id = 10; + outer_vxlan_dr->link_layer_type = 0; /* 0:ethernet; */ + + return send_mbuff; +} + + +/* תӽص豸, ײԭʼݰں */ +static int flwd_fwd_acc_pkt_input(flwd_device_handle_t *rcv_device_handle, + flwd_device_handle_t *send_device_handle, int tid, flwd_raw_pkt_t *raw_pkt) +{ + /* TODO:active_ip <---> GDEVIP ӳ, ݵǰڲݰsip, ҵgdev_ip */ + int ret; + +#if FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD /* ֻתҪsappһ */ + ///ret = flwd_fwd_to_gdev_in_sapp_vxlan_mode(send_device_handle, tid, raw_pkt); + ret = flwd_fwd_to_gdev_in_sapp_raw_marsio_mode(send_device_handle, tid, raw_pkt); +#else + void *send_mbuff ; + send_mbuff = flwd_fwd_to_gdev_pre_output(rcv_device_handle, send_device_handle, tid, raw_pkt); + if(NULL == send_mbuff){ + return -1; + } + + ret = send_device_handle->low_level_send(send_device_handle, tid, send_mbuff); + + send_device_handle->low_level_mbuff_free_after_send(send_device_handle, tid, send_mbuff); +#endif + + return ret; +} + + +/* GDEV, ײԭʼݰں */ +static int flwd_fwd_gdev_pkt_input(flwd_device_handle_t *rcv_device_handle, + flwd_device_handle_t *send_device_handle, int tid, flwd_raw_pkt_t *raw_pkt) +{ + int ret; + void *send_mbuff ; + + send_mbuff = flwd_fwd_to_acc_pre_output(rcv_device_handle, send_device_handle, tid, raw_pkt); + if(NULL == send_mbuff){ + return -1; + } + + ret = send_device_handle->low_level_send(send_device_handle, tid, send_mbuff); + + send_device_handle->low_level_mbuff_free_after_send(send_device_handle, tid, send_mbuff); + + return ret; +} + +static void flwd_fwd_nat_htable_data_free(void *data) +{ + flwd_fwd_nat_info_t *fwd_nat_info = (flwd_fwd_nat_info_t *)data; + + flwd_free(fwd_nat_info->tid, data); +} + +/* + fwdת, accessظkey㷨ͺ, dataaccessתͬ, + + accessdatanat_info, 洢innerouterԪ, + + fwddataouterԪ, ԼDNATĶԪ, ֻҪװָ, Ϊflowood. +*/ +static void *flwd_fwd_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_fwd_nat_htable_data_free, sizeof(void *)); + + ///MESA_htable_set_opt(htable, MHO_CBFUN_DATA_EXPIRE_NOTIFY, (void *)&flwd_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; +} + +static void flwd_fwd_store_session_table(int tid, flwd_raw_pkt_t *raw_pkt) +{ + flwd_vxlan_hdr_t *outer_vxlan_hdr; + const flwd_ipv4_hdr_t *outer_ip4_hdr; + const flwd_eth_hdr_t *outer_eth_hdr; + flwd_tuple5_t nat_key; + int ret; + flwd_fwd_nat_info_t *fwd_route_info; + + outer_vxlan_hdr = (flwd_vxlan_hdr_t *)((char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t)); + + if(0 == outer_vxlan_hdr->first_pkt_per_stream){ + /* װ */ + return; + } + + flwd_build_tuple4_key(tid, &nat_key, raw_pkt); + + outer_eth_hdr = (flwd_eth_hdr_t *)raw_pkt->outer_pkt_data; + outer_ip4_hdr = ((flwd_ipv4_hdr_t *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t)); + + fwd_route_info = (flwd_fwd_nat_info_t *)flwd_calloc(tid, 1, sizeof(flwd_fwd_nat_info_t)); + fwd_route_info->tid = tid; + fwd_route_info->flwd_route_info.next_gateway_ip_net = outer_ip4_hdr->ip_src.s_addr; + memcpy(fwd_route_info->flwd_route_info.next_gateway_mac, outer_eth_hdr->h_source, 6); + + ret = MESA_htable_add(flwd_thread_val[tid].nat_info_table, (uchar *)&nat_key, + sizeof(flwd_tuple5_t), (void *)fwd_route_info); + if(ret < 0){ + flwd_log(30, "FWD: save session %s to htable error, htable ret = %d.", + flwd_tuple5_ntop(tid, &nat_key), ret); + flwd_free(tid, fwd_route_info); + } + + flwd_log(10, "FWD: recv first pkt from acc gateway, save session %s to htable.", + flwd_tuple5_ntop(tid, &nat_key)); + + return; +} + +/* + return value: + 1 : IRָ; + 0 : IRָ; +*/ + +static int flwd_pkt_signature_check(flwd_tuple5_t *tuple5) +{ + unsigned int hash_val; + unsigned short ir_expect_pkt_signature; + unsigned short actual_pkt_signature; + + hash_val = flwd_tuple5_hash(tuple5, 1); + ir_expect_pkt_signature = hash_val % (FLWD_UDP_SPORT_HASH_MASK >> 8); + + if(0 == tuple5->dir_reverse){ + actual_pkt_signature = (ntohs(tuple5->sport_net_order) & FLWD_UDP_SPORT_HASH_MASK) >> 8; + }else{ + actual_pkt_signature = (ntohs(tuple5->dport_net_order) & FLWD_UDP_SPORT_HASH_MASK) >> 8; + } + if(ir_expect_pkt_signature == actual_pkt_signature){ + return 1; + } + + return 0; +} + + +/* + return value: + 1 : DZϵͳõ; + 0 : DZϵͳõ; +*/ +static int flwd_fwd_my_pkt_identify(int tid, flwd_raw_pkt_t *raw_pkt) +{ + flwd_tuple5_t nat_key; + void *hdata; + + flwd_build_tuple4_key(tid, &nat_key, raw_pkt); + + /* ӱ, ˵϶IRϵͳİ */ + hdata = MESA_htable_search(flwd_thread_val[tid].nat_info_table, (uchar *)&nat_key, sizeof(flwd_tuple5_t)); + if(hdata != NULL){ + return 1; + } + + /* ǰnat-session, ҲHASHָƵ, пDNATװ, ɨһDNAT_POLICY */ + /* TODO, + MaatɨIR_POLICY_COMPILE, ǷDNAT. + if(maat_scan() ){ + return 1; + } + */ + + + /* ӱҲDNAT, SNAT->S2Cĵ, ټ˿еHASHֵ */ + + if(flwd_pkt_signature_check(&nat_key) == 0){ + flwd_log(10, "recv tuple4: %s, but not in session_table, not found signature, must inject it back!\n", + flwd_tuple5_ntop(tid, &nat_key)); + return 0; + } + + /* TODO, + sessionҵ, пԪ, ʶIRİ, + ʱTCPа취: + + clientѽӵTCPSYN, ᷵ȷACK, client->seq + 1, ֮ͻ, ԭӲκӰ. + + Ϊ̽ͻ, TCPЭ, flowood󷢵SYN, ͨظȷACK, Ը֪; + + flowoodij˿, ʵͻʹ˿ڷSYN, ظACKACKû, ȽѲ!!! + + ԪõUDP, ô??? + */ + + return 1; +} + +static int flwd_fwd_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_FWD_LINK_ACC == 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, 1); + } + if(ret != 0){ + return FLWD_DROP; + } + + ret = flwd_protocol_stack_process(device_handle, tid, raw_pkt); + if(ret != 0){ + return FLWD_DROP; + } + + switch((int)device_handle->io_para.topo_mode){ + case TOPO_FWD_LINK_ACC: + /* ACC, Ϊflowoodϵͳİ, װҪsession */ + flwd_fwd_store_session_table(tid, raw_pkt); + flwd_fwd_acc_pkt_input(device_handle, &flwd_global_val.global_io_handle[TOPO_FWD_LINK_GDEV], tid, raw_pkt); + break; + + case TOPO_FWD_LINK_GDEV: + if(flwd_fwd_my_pkt_identify(tid, raw_pkt) == 0){ + /* ΪµIP, ʵͻ˵İ, ˴Ҫע */ + return FLWD_PASS; + } + + /* FWD, Ҫʵ, װݰsignature, ѯsession */ + flwd_fwd_gdev_pkt_input(device_handle, &flwd_global_val.global_io_handle[TOPO_FWD_LINK_ACC], tid, raw_pkt); + break; + + default: + abort(); + } + + return FLWD_DROP; /* Ĭdrop, Ϊ󲿷Ҫע */ +} + +#if FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD /* ֻתҪsappһ */ +#include "stream.h" + +static int flwd_get_sapp_thread_tid(void) +{ + int send_tid; + int opt_len; + int ret; + + ret = sapp_get_platform_opt(SPO_INDEPENDENT_THREAD_ID, &send_tid, &opt_len); + if(ret < 0){ + return -1; + } + + return send_tid; +} +#endif + + +void *flwd_packet_io_work_thread(void *arg) +{ + int ret1 = -1, ret2 = -1, ret3; + int action; + 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; /* հ */ + int success_work_times_in_recent_100 = 0; /* 100γɹĴ */ + +#if FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD /* ֻתҪsappһ */ + int sapp_send_thread_id; + printf("flwd work thread waiting for packet_io init......\n"); + sleep(10); /* Ϊ˴ڲʼ, ƽ̨ȵòٵpacket_io, ʱpacket_io_libûʼ, ʱһ!! */ + sapp_send_thread_id = flwd_get_sapp_thread_tid(); + if(sapp_send_thread_id < 0){ + abort(); + } + + flwd_global_val.global_io_handle[TOPO_FWD_LINK_ACC].sapp_send_thread_seq = sapp_send_thread_id; + flwd_global_val.global_io_handle[TOPO_FWD_LINK_GDEV].sapp_send_thread_seq = sapp_send_thread_id; +#endif + + while(1){ + dev_handle = &flwd_global_val.global_io_handle[TOPO_FWD_LINK_ACC]; + 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); + action = flwd_fwd_pkt_input(dev_handle, tseq, &raw_pkt); + if(FLWD_PASS == action){ + dev_handle->low_level_mbuff_free_after_send(dev_handle, tseq, raw_pkt.low_level_mbuff); + }else{ + dev_handle->low_level_pkt_free(dev_handle, tseq, raw_pkt.low_level_mbuff); + } + } + +#if (0 == FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD) /* ֻתҪsappһ */ + dev_handle = &flwd_global_val.global_io_handle[TOPO_FWD_LINK_GDEV]; + 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); + action = flwd_fwd_pkt_input(dev_handle, tseq, &raw_pkt); + if(FLWD_PASS == action){ + dev_handle->low_level_mbuff_free_after_send(dev_handle, tseq, raw_pkt.low_level_mbuff); + }else{ + dev_handle->low_level_pkt_free(dev_handle, tseq, raw_pkt.low_level_mbuff); + } + } +#endif + 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; + + 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_fwd_nat_table_create(); + } + + ret = flwd_packet_io_init(TOPO_FWD_LINK_ACC, TOPO_FWD_LINK_GDEV); + if(ret < 0){ + return -1; + } + + return 0; +} + +#if FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD /* ֻתΪ, Ҫsappһ */ + +static int flwd_ptk_signature_identify(struct streaminfo *pstream) +{ +#if FLWD_RUN_IN_CEIEC_TEST + + if((STREAM_TYPE_UDP == pstream->type) + && ((3784 == ntohs(pstream->addr.tuple4_v4->source)) + ||(3784 == ntohs(pstream->addr.tuple4_v4->dest)))){ + /* TODO: g_keepaliveѾDROP_PKT, Ȼûбƽ̨DROP */ + return 0; + } +#endif + + /* TODO: ݰָʶ */ + + return 1; +} + + +int flwd_fwd_to_access_gateway(struct streaminfo *a_tcp, int thread_seq, void *a_packet) +{ + flwd_device_handle_t *fwd_send_handle = &flwd_global_val.global_io_handle[TOPO_FWD_LINK_ACC]; + const flwd_ipv4_hdr_t *ipv4_hdr; + const flwd_ipv6_hdr_t *ipv6_hdr; + int inner_raw_data_len = 0; + flwd_vxlan_hdr_t *outer_vxlan_dr; + int ret; + flwd_eth_hdr_t *inner_eth_hdr; + + if(NULL == a_packet){ /* ƽ̨ʱ״̬,ûа */ + return 0; + } + + flwd_log(10, "FWD: recv pkt from gdev, inner_tuple4: %s!", + flwd_debug_print_tuple4_detail(a_packet, thread_seq)); + + if(ADDR_TYPE_IPV4 == a_tcp->addr.addrtype){ + ipv4_hdr = (flwd_ipv4_hdr_t *)a_packet; + inner_raw_data_len = ntohs(ipv4_hdr->ip_len) + sizeof(flwd_eth_hdr_t); + }else{ + ipv6_hdr = (flwd_ipv6_hdr_t *)a_packet; + inner_raw_data_len = ntohs(ipv6_hdr->ip6_payload_len) + sizeof(flwd_ipv6_hdr_t) + sizeof(flwd_eth_hdr_t); + } + + void *send_mbuff = fwd_send_handle->low_level_mbuff_malloc(fwd_send_handle, thread_seq, inner_raw_data_len + FLWD_VXLAN_OUTER_PACKET_LEN); + char *send_buf_data_ptr = fwd_send_handle->low_level_mbuff_mtod(send_mbuff); + + /* fwdյԭʼcopy͵Ļ */ + memcpy(send_buf_data_ptr+sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t)+sizeof(flwd_eth_hdr_t), + a_packet, + inner_raw_data_len); + + /* ڲethernet, eth, TODO, ڲMAC */ + 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)); + if(ADDR_TYPE_IPV4 == a_tcp->addr.addrtype){ + inner_eth_hdr->h_proto = htons(ETH_P_IP); + }else{ + inner_eth_hdr->h_proto = htons(ETH_P_IPV6); + } + + /* ָǰƶ, Ԥvxlanռ */ + + /* ײvxlanϢ, 迼Ƿ, ΪڲԪhash, vxlanַ·Ѱַ */ + + /* ײethernet, Ϊʹsocketģʽaccess, ԤռͿ, ù */ + + /* TODO: + fwdҪԴ˿лȡaccess_id, ̨access, ӳaccessIPַ, + ʱֻһ̨, ñloopback. + */ + + /* ipv4ͷ */ + flwd_sendpacket_build_ipv4(inner_raw_data_len + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t), /* ڲԭʼ + UDPͷ + vxlanͷ */ + 0, + 0x1234, + 0, + 64, + IPPROTO_UDP, + 0x0100007f, + 0x0100007f, + NULL, + 0, + (char *)send_buf_data_ptr + sizeof(flwd_eth_hdr_t)); + /* udpͷ */ + flwd_sendpacket_build_udp(inner_raw_data_len + sizeof(flwd_vxlan_hdr_t), + htons(60000 + thread_seq), /* TODO, ˴sportڲsport, ڲsportȫʶijص, vxlansport */ + htons(50000 + thread_seq), + NULL, + 0, + send_buf_data_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t)); + + /* vxlan, UDPУͿ0 */ + + /* vxlanͷ */ + outer_vxlan_dr = (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_dr, 0, sizeof(flwd_vxlan_hdr_t)); + + outer_vxlan_dr->link_id = 1; /* TODO, vxlanϢݰлȡ */ + outer_vxlan_dr->link_layer_type = 0; /* 0:ethernet; */ + + fwd_send_handle->low_level_mbuff_set_pkt_len(send_mbuff, inner_raw_data_len + FLWD_VXLAN_OUTER_PACKET_LEN); + + char debug_outer_tuple4[128]; + ret = fwd_send_handle->low_level_send(fwd_send_handle, thread_seq, send_mbuff); + if(ret < 0){ + flwd_log(30, "FWD: send pkt to access gateway error! inner_tuple4 is:%s, outer_tuple4 is:%s\n", + flwd_debug_print_tuple4_detail(a_packet, thread_seq), + flwd_debug_print_tuple4_detail_r(send_buf_data_ptr + sizeof(flwd_eth_hdr_t), debug_outer_tuple4, 128)); + }else{ + flwd_log(10, "FWD: send pkt to access gateway succ! inner_tuple4 is:%s, outer_tuple4 is:%s\n", + flwd_debug_print_tuple4_detail(a_packet, thread_seq), + flwd_debug_print_tuple4_detail_r(send_buf_data_ptr + sizeof(flwd_eth_hdr_t), debug_outer_tuple4, 128)); + } + + return ret; +} + +extern "C" char IPREUSE_TCPALL_ENTRY(struct streaminfo *a_tcp,void **pme, int thread_seq, void *a_packet) +{ + char ret = APP_STATE_GIVEME | APP_STATE_FAWPKT; + /* + NOTE: + DNAT, װ֮, DIP%access_num, һػش. + + SNAT, ڶ϶SYN/ACK, ͨı־Ƿʵ + ݵǰĶ˿ڷΧ, õĸaccess, ظ̨access. + */ + + switch(a_tcp->pktstate){ + case OP_STATE_PENDING: + if(flwd_ptk_signature_identify(a_tcp) == 0){ + return APP_STATE_DROPME | APP_STATE_FAWPKT; /* IRİ */ + } + + flwd_fwd_to_access_gateway(a_tcp, thread_seq, a_packet); + break; + + case OP_STATE_DATA: + flwd_fwd_to_access_gateway(a_tcp, thread_seq, a_packet); + ret = APP_STATE_GIVEME; /* IRİ */ + break; + + case OP_STATE_CLOSE: + flwd_fwd_to_access_gateway(a_tcp, thread_seq, a_packet); + ret = APP_STATE_DROPME; + break; + + default: + ret = APP_STATE_DROPME | APP_STATE_FAWPKT; + break; + } + + + return ret; +} + +extern "C" char IPREUSE_UDP_ENTRY(struct streaminfo *a_udp, void **pme, int thread_seq, void *a_packet) +{ + char ret = APP_STATE_GIVEME | APP_STATE_FAWPKT; + /* + NOTE: + DNAT, װ֮, DIP%access_num, һػش. + + SNAT, ڶ϶SYN/ACK, ͨı־Ƿʵ + ݵǰĶ˿ڷΧ, õĸaccess, ظ̨access. + */ + + switch(a_udp->pktstate){ + case OP_STATE_PENDING: + if(flwd_ptk_signature_identify(a_udp) == 0){ + return APP_STATE_DROPME | APP_STATE_FAWPKT; /* IRİ */ + } + flwd_fwd_to_access_gateway(a_udp, thread_seq, a_packet); + ret = APP_STATE_GIVEME | APP_STATE_FAWPKT; + break; + + + case OP_STATE_DATA: + flwd_fwd_to_access_gateway(a_udp, thread_seq, a_packet); + ret = APP_STATE_GIVEME; + break; + + case OP_STATE_CLOSE: + flwd_fwd_to_access_gateway(a_udp, thread_seq, a_packet); + ret = APP_STATE_DROPME; + break; + + default: + ret = APP_STATE_DROPME | APP_STATE_FAWPKT; /* IRİ */ + break; + } + + + return ret; + +} + +extern "C" char IPREUSE_IPv4_ENTRY(struct streaminfo *pstream,unsigned char routedir,int thread_seq, const flwd_ipv4_hdr_t * ipv4_hdr) +{ + /* + TODO: + TCP, UDPЭڴ˴, Ϊ϶˹, + ͨIPЭ, ޷ĸǸĸʵע. + + TODO: + ICMP, IGMP, GRE, ȵ, AH, ESP. + */ + + return APP_STATE_DROPME | APP_STATE_FAWPKT; +} + +extern "C" char IPREUSE_IPv6_ENTRY(const struct streaminfo *pstream,unsigned char routedir,int thread_seq, const flwd_ipv6_hdr_t *ipv6_hdr) +{ + + /* + TODO: + TCP, UDPЭڴ˴, Ϊ϶˹, + ͨIPЭ, ޷ĸǸĸʵע. + + TODO: + ICMP, IGMP, GRE, ȵ, AH, ESP. + */ + + return APP_STATE_DROPME | APP_STATE_FAWPKT; +} + +#endif + + diff --git a/src/forward/flwd_fwd_idle_call.c b/src/forward/flwd_fwd_idle_call.c new file mode 100644 index 0000000..27101d8 --- /dev/null +++ b/src/forward/flwd_fwd_idle_call.c @@ -0,0 +1,5 @@ + +int flwd_idle_call(int tid) +{ + return 0; +} diff --git a/src/forward/flwd_fwd_maat.c b/src/forward/flwd_fwd_maat.c new file mode 100644 index 0000000..9b6dda8 --- /dev/null +++ b/src/forward/flwd_fwd_maat.c @@ -0,0 +1,40 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_htable.h" +#include "MESA_list_queue.h" +#include "MESA_handle_logger.h" +#include "MESA_list_count.h" +#include "Maat_rule.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int flwd_fwd_maat_init(void) +{ +#if 0 == FLWD_NO_MAAT + int ret = flwd_maat_summon(); + if(ret < 0){ + return -1; + } + + flwd_maat_table_register((int)FLWD_MAAT_TB_IR_POLICY_COMPILE); + flwd_maat_table_register((int)FLWD_MAAT_TB_IR_POLICY_GROUP); + + /* SYNɨǷDNAT */ + flwd_maat_table_register((int)FLWD_MAAT_TB_IR_POLICY_IP); + + /* SYN/ACK, ɨIR_DYN_CONN_IP, ߸ݰָʶ */ + flwd_maat_table_register((int)FLWD_MAAT_TB_IR_DYN_CONN_IP); + +#endif + + return 0; +} + diff --git a/src/packet_io/Makefile b/src/packet_io/Makefile new file mode 100644 index 0000000..5a2d790 --- /dev/null +++ b/src/packet_io/Makefile @@ -0,0 +1,34 @@ +#CC=gcc +CC=g++ +CCC=g++ + +TARGET=flwd_io_pcap.so flwd_io_socket.so flwd_packet_io.o + +CFLAGS +=-g -Wall -fPIC -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= ../../bin/ip_reuse_io_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) $< + +flwd_io_pcap.so:flwd_packet_io_pcap.o + $(CCC) -o $@ -shared -g -Wall $(CFLAGS) $(H_DIR) $^ -lpcap + cp $@ $(LIBPATH) + +flwd_io_socket.so:flwd_packet_io_socket.o + $(CCC) -o $@ -shared -g -Wall $(CFLAGS) $(H_DIR) $^ + cp $@ $(LIBPATH) + +clean: + rm -f *.o diff --git a/src/packet_io/flwd_io_pcap.so b/src/packet_io/flwd_io_pcap.so new file mode 100644 index 0000000..7af3822 Binary files /dev/null and b/src/packet_io/flwd_io_pcap.so differ diff --git a/src/packet_io/flwd_io_socket.so b/src/packet_io/flwd_io_socket.so new file mode 100644 index 0000000..7db273b Binary files /dev/null and b/src/packet_io/flwd_io_socket.so differ diff --git a/src/packet_io/flwd_packet_io.c b/src/packet_io/flwd_packet_io.c new file mode 100644 index 0000000..a6f8449 --- /dev/null +++ b/src/packet_io/flwd_packet_io.c @@ -0,0 +1,193 @@ +/* + ĸӿ, ģʽ, + ÿж߳, TOPO_ACC_LINK_USER, TOPO_ACC_LINK_FWDӦùý/߳, + ΪڲNATת, շʹͬһ, Ƕ߳, Ҫ. + + , ֧TOPO_ACC_LINK_USER, TOPO_ACC_LINK_FWDΪͬIJģʽ, + ÷ģʽ֮лȡݰ. +*/ + +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_handle_logger.h" +#include "MESA_prof_load.h" +#include +#include +#include +#include +#include +#include + + +typedef struct{ + flwd_cap_mode_t cap_mode; + char *lib_name; +}flwd_io_lib_name_type_t; + + +static const flwd_io_lib_name_type_t g_packet_io_type_name_info[] = +{ + {CAP_MODEL_PAG , (char *)"flwd_io_pag.so" }, + {CAP_MODEL_PCAP_ONLINE , (char *)"flwd_io_pcap.so" }, + {CAP_MODEL_SOCKET , (char *)"flwd_io_socket.so" }, + {CAP_MODEL_PFRING , (char *)"flwd_io_pfring.so" }, + {CAP_MODEL_DPDK , (char *)"flwd_io_dpdk.so" }, + {CAP_MODEL_PPF , (char *)"flwd_io_ppf.so" }, + {CAP_MODEL_NPACKET , (char *)"flwd_io_npacket.so" }, + {CAP_MODEL_QNF , (char *)"flwd_io_qnf.so" }, + {CAP_MODEL_N95 , (char *)"flwd_io_n95.so" }, + {CAP_MODEL_PCAP_DUMPLIST , (char *)"flwd_io_pcap.so"}, + {CAP_MODEL_TOPSEC , (char *)"flwd_io_topsec.so"}, + {CAP_MODEL_IPFILE , (char *)"flwd_io_ipfile.so"}, + {CAP_MODEL_MARSIOV4 , (char *)"flwd_io_marsio.so"}, + {CAP_MODEL_AGENT_SMITH , (char *)"flwd_io_agent_smith.so"}, + {CAP_MODEL_DPDK_VXLAN , (char *)"flwd_io_dpdk_vxlan.so"}, + {CAP_MODEL_MARSIOV4_VXLAN , (char *)"flwd_io_marsio_vxlan.so"}, + {CAP_MODEL_PAG_MARSIO , (char *)"flwd_io_pag_marsio.so"}, +}; + +const flwd_packet_io_cfg_para_t g_packet_io_cfg_para[__TOPO_MODE_MAX] = +{ + {TOPO_ACC_LINK_USER, FLWD_MACRO_TO_STRING(TOPO_ACC_LINK_USER), "#todo"}, + {TOPO_ACC_LINK_FWD, FLWD_MACRO_TO_STRING(TOPO_ACC_LINK_FWD), "#todo"}, + {TOPO_FWD_LINK_ACC, FLWD_MACRO_TO_STRING(TOPO_FWD_LINK_ACC), "#doto"}, + {TOPO_FWD_LINK_GDEV, FLWD_MACRO_TO_STRING(TOPO_FWD_LINK_GDEV), "#doto"}, +}; + +static int flwd_packet_io_lib_load(flwd_device_handle_t *global_dev_handle) +{ + char full_lib_path[PATH_MAX]; + void *dlopen_handle; + + switch((int)global_dev_handle->io_para.cap_mode){ + case CAP_MODEL_PCAP_ONLINE: + case CAP_MODEL_SOCKET: + case CAP_MODEL_MARSIOV4: + break; + + default: + flwd_log(RLOG_LV_FATAL, "not support cap_mode:%d\n", (int)global_dev_handle->io_para.cap_mode); + return -1; + break; + } + + snprintf(full_lib_path, PATH_MAX, "%s/%s", "ip_reuse_io_lib", g_packet_io_type_name_info[(int)global_dev_handle->io_para.cap_mode].lib_name); + + dlopen_handle = dlopen(full_lib_path, RTLD_LAZY | RTLD_LOCAL); + if(NULL == dlopen_handle){ + flwd_log(RLOG_LV_FATAL, "dlopen %s error, %s", full_lib_path, dlerror()); + return -1; + } + global_dev_handle->low_level_io_init = (int (*)(struct __flwd_device_handle *h))dlsym(dlopen_handle, "low_level_io_init"); + global_dev_handle->low_level_io_run = (void (*)(struct __flwd_device_handle *h))dlsym(dlopen_handle, "low_level_io_run"); + global_dev_handle->low_level_pkt_recv = (int (*)(struct __flwd_device_handle *h, int tid, void **mbuff))dlsym(dlopen_handle, "low_level_pkt_recv"); + global_dev_handle->low_level_pkt_free = (void (*)(struct __flwd_device_handle *h, int tid, void *mbuff))dlsym(dlopen_handle, "low_level_pkt_free"); + global_dev_handle->low_level_mbuff_malloc = (void * (* )(struct __flwd_device_handle *h, int tid, int len)) dlsym(dlopen_handle, "low_level_mbuff_malloc"); + global_dev_handle->low_level_mbuff_free = (void (* )(struct __flwd_device_handle *h, int, void *mbuff)) dlsym(dlopen_handle, "low_level_mbuff_free"); + global_dev_handle->low_level_mbuff_free_after_send = (void (* )(struct __flwd_device_handle *h, int, void *mbuff)) dlsym(dlopen_handle, "low_level_mbuff_free_after_send"); + global_dev_handle->low_level_mbuff_mtod = (char * (* )(void *mbuff))dlsym(dlopen_handle, "low_level_mbuff_mtod"); + global_dev_handle->low_level_mbuff_data_append = (char * (*)(void *mbuff, const char *user_data, int user_data_len))dlsym(dlopen_handle, "low_level_mbuff_data_append"); + global_dev_handle->low_level_mbuff_data_forward = (char * (*)(void *mbuff, int n))dlsym(dlopen_handle, "low_level_mbuff_data_forward"); + global_dev_handle->low_level_mbuff_data_rearward = (char * (*)(void *mbuff, int n))dlsym(dlopen_handle, "low_level_mbuff_data_rearward"); + global_dev_handle->low_level_mbuff_get_pkt_len = (int (*)(void *mbuff))dlsym(dlopen_handle, "low_level_mbuff_get_pkt_len"); + global_dev_handle->low_level_mbuff_set_pkt_len = (void (*)(void *mbuff, int pkt_len)) dlsym(dlopen_handle, "low_level_mbuff_set_pkt_len"); + global_dev_handle->low_level_send = (int (*)(struct __flwd_device_handle *h, int tid, void *mbuff))dlsym(dlopen_handle, "low_level_send"); + + return 0; +} + +static void *flwd_packet_io_run_thread(void *arg) +{ + flwd_device_handle_t *global_io_handle = (flwd_device_handle_t *)arg; + + global_io_handle->low_level_io_run(global_io_handle); + + while(1){ + pause(); + } + + return NULL; +} + + + +void flwd_packet_io_run(void) +{ + int i; + pthread_t recv_thread_pid[FLWD_MAX_THREAD_NUM]; + pthread_t run_thread_pid[FLWD_MAX_THREAD_NUM]; + static int thread_seq[FLWD_MAX_THREAD_NUM]; + + for(i = 0; i < flwd_cfg_val.tot_thread_count; i++){ + thread_seq[i] = i; + pthread_create(&recv_thread_pid[i], NULL, flwd_packet_io_work_thread, (void *)&thread_seq[i]); + } + + /* NOTE: + ijЩײIOԼ, ܵio_runհ̾Ҳ޷, pcap_loop()Ⱥ, Ҫ̬հ߳, + marsioIO, հѯģʽ, flwd_packet_io_run_thread̴߳һֱ, ʵ. + */ + for(i = 0; i < __TOPO_MODE_MAX; i++){ + if(flwd_global_val.global_io_handle[i].low_level_io_handle != NULL){ + pthread_create(&run_thread_pid[i], NULL, flwd_packet_io_run_thread, (void *)&flwd_global_val.global_io_handle[i]); + } + } +} + +/* + ÿسʼ豸. +*/ +int flwd_packet_io_init(flwd_topology_t first_top_mode, flwd_topology_t second_top_mode) +{ + char str_tmp[128]; + int ret, int_tmp; + int i; + + for(i = 0; i < (int)__TOPO_MODE_MAX; i++){ + if((i != first_top_mode) && (i != second_top_mode)){ + continue; + } + /* NOTE: ȡļ, ȡز */ + flwd_global_val.global_io_handle[i].io_para.topo_mode = (flwd_topology_t)i; + + MESA_load_profile_int_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[i].cfg_file_section, "cap_mode", &int_tmp, 0); + if(int_tmp <= 0 || int_tmp > CAP_MODEL_PAG_MARSIO){ + flwd_log(RLOG_LV_FATAL, "get config %s->cap_mode error!", g_packet_io_cfg_para[i].cfg_file_section); + return -1; + } + flwd_global_val.global_io_handle[i].io_para.cap_mode = (flwd_cap_mode_t)int_tmp; + + MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[i].cfg_file_section, "device_name", str_tmp, 128, "#"); + if('#' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "get config %s->device_name error!", g_packet_io_cfg_para[i].cfg_file_section); + return -1; + } + flwd_global_val.global_io_handle[i].io_para.device_name = strdup(str_tmp); + + MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[i].cfg_file_section, "pkt_filter", str_tmp, 128, "#"); + if('#' == str_tmp[0]){ + flwd_global_val.global_io_handle[i].io_para.pkt_filter = NULL; + }else{ + flwd_global_val.global_io_handle[i].io_para.pkt_filter = strdup(str_tmp); + } + + /* NOTE: dlopen򿪵ײIO, io_pcap.so, io_marsio.so, ȡغָ */ + ret = flwd_packet_io_lib_load(&flwd_global_val.global_io_handle[i]); + if(ret < 0){ + flwd_log(RLOG_LV_FATAL, "%s, flwd_packet_io_lib_load() error!", g_packet_io_cfg_para[i].cfg_file_section); + return -1; + } + + ret = flwd_global_val.global_io_handle[i].low_level_io_init(&flwd_global_val.global_io_handle[i]); + if(ret < 0){ + flwd_log(RLOG_LV_FATAL, "%s low_level_init() error!", g_packet_io_cfg_para[i].cfg_file_section); + return -1; + } + } + + flwd_log(RLOG_LV_DEBUG, "flwd_packet_io_init success!"); + + return 0; +} + diff --git a/src/packet_io/flwd_packet_io_pcap.c b/src/packet_io/flwd_packet_io_pcap.c new file mode 100644 index 0000000..adb584e --- /dev/null +++ b/src/packet_io/flwd_packet_io_pcap.c @@ -0,0 +1,428 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include +#include "MESA_list_queue.h" +#include "MESA_handle_logger.h" +#include "MESA_prof_load.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +/* Ҫ̬dlopenȡ, ʹC淶 */ +extern "C" { +#endif + + +typedef struct { + pthread_t pid; + unsigned char thread_seq; + int sd_raw_eth; /* ײ㷢socket */ + struct sockaddr sock_addr; + MESA_lqueue_head pkt_queue; +}pcap_work_thread_t; + +typedef struct{ + char *__data_buf; /* mbuffͷָ */ + char *data_actual_ptr; /* ǰʵʴ洢ָ */ + int __data_buf_max_len; /* mbuff󻺴泤, FLWD_LINK_MTU */ + int data_actual_len; /* ǰʵʴ洢ݳ */ +}pcap_mbuff_t; + +/* pcapģʽڲṹ */ +typedef struct{ + int tot_thread_count; + pcap_t *pcap_dev_handle; + pcap_work_thread_t pcap_io_thread_para[FLWD_MAX_THREAD_NUM]; + pcap_mbuff_t pcap_send_buf[FLWD_MAX_THREAD_NUM]; /* , ʼʱ, Ժ󷢰ÿζ̬malloc/free */ +}flwd_device_handle_pcap_t; + +typedef struct{ + char *pkt_data; + int pkt_len; +}pcap_queue_item_t; + +/* 2012-04-10 LiJia add, ȡMACַ +: + device: + mac: 洢MACַ,Ϊ, + MACַΪ11:22:33:44:55:66,mac[0]Ϊ0x11,mac[5]Ϊ0x66. +ֵ: + 0: + -1: +*/ +static int MESA_get_dev_mac(const char *device, unsigned char mac[6]) +{ + struct ifreq ifr; + int fd; + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if(fd < 0) + { + return -1; + } + + memset(ifr.ifr_ifrn.ifrn_name, 0, sizeof(ifr.ifr_ifrn.ifrn_name)); + strncpy(ifr.ifr_ifrn.ifrn_name, device, sizeof(ifr.ifr_ifrn.ifrn_name)); + if(ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) + { + printf("Cann't get hwaddr of %s:%s\n", device, strerror(errno)); + goto err_exit; + } + + if(ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) + { + printf("'%s' is not ethernet interface!\n", device); + goto err_exit; + } + + memcpy(mac, ifr.ifr_ifru.ifru_addr.sa_data, 6); + + close(fd); + + return 0; + +err_exit: + close(fd); + return -1; +} + +static inline int flwd_pcap_dispatch_thread(flwd_device_handle_pcap_t *pcap_io_handle, const u_char *data) +{ + int to_work_thread_seq; + const flwd_eth_hdr_t *flwd_eth_hdr = (flwd_eth_hdr_t *)data; + const flwd_ipv4_hdr_t *flwd_ip_hdr; + + if(ETH_P_IP == ntohs(flwd_eth_hdr->h_proto)){ + flwd_ip_hdr = (flwd_ipv4_hdr_t *)(data + sizeof(flwd_eth_hdr_t)); + to_work_thread_seq = (flwd_ip_hdr->ip_src.s_addr ^ flwd_ip_hdr->ip_dst.s_addr) % pcap_io_handle->tot_thread_count; + }else{ + to_work_thread_seq = 0;/* ЭĬ0 */ + } + + return to_work_thread_seq; +} + + + +static pcap_mbuff_t *flwd_pcap_create_new_mbuff(u_char *data, int datalen) +{ + pcap_mbuff_t *pcap_mbuff; + + pcap_mbuff = (pcap_mbuff_t *)calloc(1, sizeof(pcap_mbuff_t)); + + pcap_mbuff->__data_buf = (char *)malloc(datalen + FLWD_VXLAN_OUTER_PACKET_LEN); /* Ԥvxlanͷ */ + pcap_mbuff->__data_buf_max_len = datalen + FLWD_VXLAN_OUTER_PACKET_LEN; + + + pcap_mbuff->data_actual_ptr = pcap_mbuff->__data_buf + FLWD_VXLAN_OUTER_PACKET_LEN; + pcap_mbuff->data_actual_len = datalen; + + memcpy(pcap_mbuff->data_actual_ptr, data, datalen); + + return pcap_mbuff; +} + + +static void flwd_pcap_pkt_handle(u_char *user, const struct pcap_pkthdr *hdr, const u_char *data) +{ + int to_work_thread_seq; + pcap_mbuff_t *pcap_mbuff; + flwd_device_handle_pcap_t *pcap_io_handle = (flwd_device_handle_pcap_t *)user; + + to_work_thread_seq = flwd_pcap_dispatch_thread(pcap_io_handle, data); + + pcap_mbuff = flwd_pcap_create_new_mbuff((u_char *)data, hdr->caplen); + + /* NOTE: ˴ӿ, Ϊpcap_loopڶ߳Ŀռ, Ӱ */ + int ret = MESA_lqueue_join_tail(pcap_io_handle->pcap_io_thread_para[to_work_thread_seq].pkt_queue, &pcap_mbuff, sizeof(void *)); + if(ret < 0){ + free(pcap_mbuff->__data_buf); + free(pcap_mbuff); + printf("pcap io thread MESA_lqueue_join_tail() error, ret=%d\n", ret); + } + +} + +static int pcap_low_level_io_init(flwd_device_handle_t *global_dev_handle) +{ + int i; + char pcap_errbuf[PCAP_ERRBUF_SIZE]; + char str_tmp[128]; + struct bpf_program bpf_filter; + + flwd_device_handle_pcap_t *pcap_io_handle = (flwd_device_handle_pcap_t *)calloc(1, sizeof(flwd_device_handle_pcap_t)); + + pcap_io_handle->pcap_dev_handle = pcap_open_live(global_dev_handle->io_para.device_name, 4096, 1, 1, pcap_errbuf); + if(NULL == pcap_io_handle->pcap_dev_handle){ + flwd_log(RLOG_LV_FATAL, "pcap_open_live() error, %s\n", pcap_errbuf); + return -1; + } + /* TODO, set filter */ + if(global_dev_handle->io_para.pkt_filter != NULL){ + if(pcap_compile(pcap_io_handle->pcap_dev_handle, &bpf_filter, (char *)global_dev_handle->io_para.pkt_filter, 1, 0) < 0){ + flwd_log(RLOG_LV_FATAL, "pcap_compile() error, invalid pkt_filter: %s\n", global_dev_handle->io_para.pkt_filter); + return -1; + } + + pcap_setfilter(pcap_io_handle->pcap_dev_handle, &bpf_filter); + } + + pcap_setdirection(pcap_io_handle->pcap_dev_handle, PCAP_D_IN); /* ֻհ */ + + for(i = 0; i < global_dev_handle->tot_thread_count; i++){ + pcap_io_handle->pcap_io_thread_para[i].thread_seq = i; + pcap_io_handle->pcap_send_buf[i].__data_buf = (char *)malloc(FLWD_LINK_MTU); + pcap_io_handle->pcap_send_buf[i].__data_buf_max_len = FLWD_LINK_MTU; + pcap_io_handle->pcap_io_thread_para[i].sd_raw_eth = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); + + snprintf(pcap_io_handle->pcap_io_thread_para[i].sock_addr.sa_data, + sizeof(pcap_io_handle->pcap_io_thread_para[i].sock_addr.sa_data), + "%s", global_dev_handle->io_para.device_name); + + pcap_io_handle->pcap_io_thread_para[i].pkt_queue = MESA_lqueue_create(1, 50000); + } + + MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section, "addr_para", str_tmp, 128, "#"); + if('#' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "get config %s->addr_para error!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section); + return -1; + } + if(inet_pton(AF_INET, str_tmp, &global_dev_handle->io_para.device_ip_net_order) <= 0){ + flwd_log(RLOG_LV_FATAL, "config %s->addr_para type invalid!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section); + return -1; + } + + MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section, "addr_mask", str_tmp, 128, "#"); + if('#' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "get config %s->addr_mask error!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section); + return -1; + } + if(inet_pton(AF_INET, str_tmp, &global_dev_handle->io_para.device_ip_mask_net_order) <= 0){ + flwd_log(RLOG_LV_FATAL, "config %s->addr_mask type invalid!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section); + return -1; + } + + MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section, "gateway_ip", str_tmp, 128, "#"); + if('#' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "get config %s->gateway_ip error!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section); + return -1; + } + if(inet_pton(AF_INET, str_tmp, &global_dev_handle->io_para.gateway_ip_net_order) <= 0){ + flwd_log(RLOG_LV_FATAL, "config %s->gateway_ip type invalid!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section); + return -1; + } + + + MESA_get_dev_mac(global_dev_handle->io_para.device_name, global_dev_handle->io_para.local_mac_addr); + + pcap_io_handle->tot_thread_count = global_dev_handle->tot_thread_count; + global_dev_handle->low_level_io_handle = (void *)pcap_io_handle; + + return 0; +} + +static int pcap_low_level_send(flwd_device_handle_t *global_dev_handle, int tid, void *mbuff) +{ + int ret; + pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff; + flwd_device_handle_pcap_t *pcap_io_handle = (flwd_device_handle_pcap_t *)global_dev_handle->low_level_io_handle; + + ret = sendto(pcap_io_handle->pcap_io_thread_para[tid].sd_raw_eth, + pcap_mbuff->data_actual_ptr, + pcap_mbuff->data_actual_len, + MSG_DONTWAIT, + (const struct sockaddr *)&pcap_io_handle->pcap_io_thread_para[tid].sock_addr, + sizeof(struct sockaddr)); + + return ret; +} + + + + +int low_level_pkt_recv(flwd_device_handle_t *g_dev_handle, int tid, void **mbuff) +{ + int ret, try_times; + pcap_mbuff_t *pcap_mbuff; + long recv_len; + flwd_device_handle_pcap_t *pcap_io_handle = (flwd_device_handle_pcap_t *)g_dev_handle->low_level_io_handle; + + recv_len = sizeof(void *); + + for(try_times = 0; try_times < 20; try_times++){ + /* NOTE: Ϊtrylock, dzʧ, Լ */ + ret = MESA_lqueue_try_get_head(pcap_io_handle->pcap_io_thread_para[tid].pkt_queue, &pcap_mbuff, &recv_len); + switch(ret){ + case 0: //OK + goto done; + break; + + case -5: //empty, no packet + return -1; + } + } + + if(ret < 0){ + return -1; + } + +done: + *mbuff = (void *)pcap_mbuff; + + return pcap_mbuff->data_actual_len; +} + +void low_level_pkt_free(flwd_device_handle_t *g_dev_handle, int tid, void *mbuff) +{ + pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff; + + free(pcap_mbuff->__data_buf); + free(pcap_mbuff); + + return; +} + + +void *low_level_mbuff_malloc(flwd_device_handle_t *g_dev_handle, int tid, int len) +{ + ///flwd_device_handle_pcap_t *pcap_io_handle = (flwd_device_handle_pcap_t *)g_dev_handle->low_level_io_handle; + + pcap_mbuff_t *mbuff = (pcap_mbuff_t *)malloc(sizeof(pcap_mbuff_t)); + + mbuff->__data_buf = (char *)malloc(FLWD_LINK_MTU); + mbuff->data_actual_ptr = mbuff->__data_buf + FLWD_VXLAN_OUTER_PACKET_LEN; + mbuff->__data_buf_max_len = FLWD_LINK_MTU; + mbuff->data_actual_len = 0; + + return (void *)mbuff; +} + +char *low_level_mbuff_mtod(void *mbuff) +{ + pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff; + + return (char *)pcap_mbuff->data_actual_ptr; +} + +void low_level_mbuff_free(struct __flwd_device_handle *h, int tid, void *mbuff) +{ + pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff; + + free(pcap_mbuff->__data_buf); + pcap_mbuff->data_actual_len = 0; + pcap_mbuff->__data_buf_max_len = 0; + free(mbuff); +} + +void low_level_mbuff_free_after_send(flwd_device_handle_t *g_dev_handle, int tid, void *mbuff) +{ + /* pcapģʽԶfree, ٴεfree */ + low_level_mbuff_free(g_dev_handle, tid, mbuff); +} + + +void low_level_mbuff_send_back(flwd_device_handle_t *g_dev_handle, int tid, void *mbuff) +{ + /* pcapģʽʱûעgdevݰ, պ */ + return; +} + +/* + mbuff׷user_data. + + return value: + ʼλ; +*/ +char * low_level_mbuff_data_append(void *mbuff, const char *user_data, int user_data_len) +{ + pcap_mbuff_t *pcap_mbuff= (pcap_mbuff_t *)mbuff; + + assert(user_data_len <= pcap_mbuff->__data_buf_max_len - pcap_mbuff->data_actual_len); + + memcpy(pcap_mbuff->data_actual_ptr, user_data, user_data_len); + pcap_mbuff->data_actual_len += user_data_len; + + return (char *)pcap_mbuff->data_actual_ptr; +} + +/* ָǰƶNֽ, ݳԶN, ݰ֮ǰͷ, vxlan */ +char *low_level_mbuff_data_forward(void *mbuff, int n) +{ + pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff; + + assert(n <= pcap_mbuff->data_actual_ptr - pcap_mbuff->__data_buf); + + pcap_mbuff->data_actual_ptr -= n; /* ǰƶ */ + pcap_mbuff->data_actual_len += n; + + return (char *)pcap_mbuff->data_actual_ptr; +} + + +/* ָƶNֽ, ݳԶN, ǰݰijЩͷ, ȥvxlanͷ */ +char * low_level_mbuff_data_rearward(void *mbuff, int n) +{ + pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff; + + assert(n <= pcap_mbuff->__data_buf_max_len - pcap_mbuff->data_actual_len); + + pcap_mbuff->data_actual_ptr += n; + pcap_mbuff->data_actual_len -= n; + + return pcap_mbuff->data_actual_ptr; +} + + + +int low_level_mbuff_get_pkt_len(void *mbuff) +{ + pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff; + + return pcap_mbuff->data_actual_len; +} + +void low_level_mbuff_set_pkt_len(void *mbuff, int pkt_len) +{ + pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff; + + pcap_mbuff->data_actual_len = pkt_len; +} + + +int low_level_send(flwd_device_handle_t *global_dev_handle, int tid, void *mbuff) +{ + return pcap_low_level_send(global_dev_handle, tid, mbuff); +} + +/* ˺ѭ, һֱ */ +void low_level_io_run(flwd_device_handle_t *global_io_handle) +{ + ///int i; + ///pthread_t pid; + + flwd_device_handle_pcap_t *pcap_io_handle = (flwd_device_handle_pcap_t *)global_io_handle->low_level_io_handle; + + while(1){ + pcap_loop(pcap_io_handle->pcap_dev_handle, -1, flwd_pcap_pkt_handle, (u_char *)pcap_io_handle); + } + + return; +} + +int low_level_io_init(flwd_device_handle_t *global_dev_handle) +{ + return pcap_low_level_io_init(global_dev_handle); +} + +#ifdef __cplusplus +} +#endif + diff --git a/src/packet_io/flwd_packet_io_socket.c b/src/packet_io/flwd_packet_io_socket.c new file mode 100644 index 0000000..6dad448 --- /dev/null +++ b/src/packet_io/flwd_packet_io_socket.c @@ -0,0 +1,376 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include +#include "MESA_list_queue.h" +#include "MESA_handle_logger.h" +#include "MESA_prof_load.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +/* Ҫ̬dlopenȡ, ʹC淶 */ +extern "C" { +#endif + + +typedef struct { + pthread_t pid; + unsigned char thread_seq; + int sd; /* socket, UDP, DGRAMģʽ */ + struct sockaddr sock_addr; +}socket_work_thread_t; + +typedef struct{ + char *__data_buf; /* mbuffͷָ */ + char *data_actual_ptr; /* ǰʵʴ洢ָ, MACʼûҲԤռαһ, socketģʽ */ + int __data_buf_max_len; /* mbuff󻺴泤, FLWD_LINK_MTU */ + int data_actual_len; /* ǰʵʴ洢ݳ */ +}socket_mbuff_t; + +/* pcapģʽڲṹ */ +typedef struct{ + int tot_thread_count; + int *socket_dev_handle; /* sdָ */ + socket_work_thread_t socket_io_thread_para[FLWD_MAX_THREAD_NUM]; + socket_mbuff_t socket_send_buf[FLWD_MAX_THREAD_NUM]; /* , ʼʱ, Ժ󷢰ÿζ̬malloc/free */ +}flwd_device_handle_socket_t; + + + +/* ˺ѭ, һֱ */ +void low_level_io_run(flwd_device_handle_t *global_io_handle) +{ + /* socketģʽ, initɹ, ӿ, ֱrecv, send */ + (void )global_io_handle; + + return; +} + + +static socket_mbuff_t *flwd_socket_create_new_mbuff(int datalen) +{ + socket_mbuff_t *sock_mbuff; + + sock_mbuff = (socket_mbuff_t *)calloc(1, sizeof(socket_mbuff_t)); + + sock_mbuff->__data_buf = (char *)malloc(datalen + FLWD_VXLAN_OUTER_PACKET_LEN); /* Ԥvxlanͷ */ + sock_mbuff->__data_buf_max_len = datalen + FLWD_VXLAN_OUTER_PACKET_LEN; + + + sock_mbuff->data_actual_ptr = sock_mbuff->__data_buf + FLWD_VXLAN_OUTER_PACKET_LEN; + sock_mbuff->data_actual_len = datalen; + + return sock_mbuff; +} + +/* socket addr_para: addr_para=127.0.0.1:50000 */ +int flwd_socket_addr_para_parse(char *cfg_line, unsigned int *sock_addr_ip_net_order, unsigned short *sock_addr_port_host_order) +{ + const char *delim = ": "; + char *save_ptr; + char *section; + int tmp; + + section = strtok_r(cfg_line, delim, &save_ptr); + if(inet_pton(AF_INET, cfg_line, sock_addr_ip_net_order) <= 0){ + return -1; + } + + section = strtok_r(NULL, delim, &save_ptr); + if(NULL == section){ + return -1; + } + + tmp = atoi(section); + if(tmp <= 0 || tmp > 65535){ + return -1; + } + + *sock_addr_port_host_order = (unsigned short)tmp; + + while(strtok_r(NULL, delim, &save_ptr)); + + return 0; +} + +/* Ϊgdbϵ㷽, ÿio_libԼڲصĺ */ +static int socket_low_level_io_init(flwd_device_handle_t *global_dev_handle) +{ + int i, tmp_int; + char str_tmp[128]; + unsigned int sock_addr_ip_net_order = 0; /* socketģʽIP */ + unsigned short sock_addr_port_host_order; /* ʼ˿, һ󶨴ӵǰ˿ڿʼport + thread_count */ + struct sockaddr_in sockadd; + + flwd_device_handle_socket_t *socket_io_handle = (flwd_device_handle_socket_t *)calloc(1, sizeof(flwd_device_handle_socket_t)); + + /* socket addr_para: addr_para=60000, ʾذ󶨵ʼ˿, Լthread_num˿ */ + MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section, "addr_para", str_tmp, 128, "#"); + if('#' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "get config %s->addr_para error!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section); + return -1; + } + +#if 0 + ret = flwd_socket_addr_para_parse(str_tmp, &sock_addr_ip_net_order, &sock_addr_port_host_order); + if(ret < 0){ + flwd_log(RLOG_LV_FATAL, "parse config %s->addr_para %s error!", + g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section, str_tmp); + return -1; + } +#else + tmp_int = atoi(str_tmp); + if((tmp_int <= 0) || (tmp_int > 65535)){ + flwd_log(RLOG_LV_FATAL, "%s config %s->addr_para error!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section); + return -1; + } +#endif + + sock_addr_port_host_order = (unsigned short)tmp_int; + + for(i = 0; i < global_dev_handle->tot_thread_count; i++){ + socket_io_handle->socket_io_thread_para[i].thread_seq = i; + socket_io_handle->socket_send_buf[i].__data_buf = (char *)malloc(FLWD_LINK_MTU); + socket_io_handle->socket_send_buf[i].__data_buf_max_len = FLWD_LINK_MTU; + socket_io_handle->socket_io_thread_para[i].sd = socket(AF_INET, SOCK_DGRAM, 0); + + bzero(&sockadd, sizeof(sockadd)); + sockadd.sin_family = AF_INET; + sockadd.sin_addr.s_addr = sock_addr_ip_net_order; + sockadd.sin_port = htons(sock_addr_port_host_order + i); + + if(bind(socket_io_handle->socket_io_thread_para[i].sd, (struct sockaddr *) &sockadd, sizeof(sockadd)) < 0){ + flwd_log(RLOG_LV_FATAL, "Socket bind port %u error, %s!\n", sock_addr_port_host_order + i, strerror(errno)); + return -1; + } + } + + global_dev_handle->io_para.device_ip_net_order = sock_addr_ip_net_order; + global_dev_handle->io_para.socket_port_net_order = htons(sock_addr_port_host_order); + + socket_io_handle->tot_thread_count = global_dev_handle->tot_thread_count; + global_dev_handle->low_level_io_handle = (void *)socket_io_handle; + + return 0; +} + +#if FLWD_NAT_SPORT_VOLATILE +static struct sockaddr_in g_remote_addr; +#endif + + +static int socket_low_level_send(flwd_device_handle_t *global_dev_handle, int tid, void *mbuff) +{ + int ret; + socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff; + flwd_device_handle_socket_t *sock_io_handle = (flwd_device_handle_socket_t *)global_dev_handle->low_level_io_handle; + struct sockaddr_in sockadd; + const flwd_ipv4_hdr_t *ipv4_hdr = (flwd_ipv4_hdr_t *) (sock_mbuff->data_actual_ptr + sizeof(flwd_eth_hdr_t)); + const flwd_udp_hdr_t *udph = (flwd_udp_hdr_t *)(sock_mbuff->data_actual_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t)); + + sockadd.sin_family = AF_INET; + +#if FLWD_NAT_SPORT_VOLATILE + sockadd.sin_addr.s_addr = g_remote_addr.sin_addr.s_addr; + sockadd.sin_port = g_remote_addr.sin_port; +#else + sockadd.sin_addr.s_addr = ipv4_hdr->ip_dst.s_addr; + sockadd.sin_port = udph->uh_dport; +#endif + + ret = sendto(sock_io_handle->socket_io_thread_para[tid].sd, + sock_mbuff->data_actual_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t), /* ϲӦöĬϴmac㿪ʼ, ˴ʹsocketģʽ, ϵͳװMAC,IP,UDP, vxlanMACͷ+ipͷ+udpͷ */ + sock_mbuff->data_actual_len - sizeof(flwd_eth_hdr_t) - sizeof(flwd_ipv4_hdr_t) - sizeof(flwd_udp_hdr_t), /* ϲӦöĬϴmac㿪ʼ, ˴ʹsocketģʽ, ϵͳװMAC,IP,UDP, vxlanMACͷ+ipͷ+udpͷ */ + MSG_DONTWAIT, + (const struct sockaddr *)&sockadd, + sizeof(struct sockaddr)); + + return ret; +} + +int low_level_pkt_recv(flwd_device_handle_t *g_dev_handle, int tid, void **mbuff) +{ + int ret; + socket_mbuff_t *sock_mbuff; + char sock_rcv_buf[FLWD_LINK_MTU]; + flwd_device_handle_socket_t *socket_io_handle = (flwd_device_handle_socket_t *)g_dev_handle->low_level_io_handle; + flwd_eth_hdr_t *ehdr; + flwd_ipv4_hdr_t *ipv4_hdr; + struct sockaddr_in local_remote_addr; + socklen_t addr_len = sizeof(local_remote_addr); + + ret = recvfrom(socket_io_handle->socket_io_thread_para[tid].sd, sock_rcv_buf, FLWD_LINK_MTU, MSG_DONTWAIT, (struct sockaddr *)&local_remote_addr, &addr_len); + + if(ret > 0){ + sock_mbuff = flwd_socket_create_new_mbuff(ret + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t)); + + /* αһmacʼԭʼ, ģvxlanethernet */ + ehdr = (flwd_eth_hdr_t *)(sock_mbuff->data_actual_ptr); + ehdr->h_proto = htons(ETH_P_IP); + + /* ģvxlanipv4 */ + ipv4_hdr = (flwd_ipv4_hdr_t *) (sock_mbuff->data_actual_ptr + sizeof(flwd_eth_hdr_t)); + ipv4_hdr->ip_v = 4; + ipv4_hdr->ip_hl = 5; + ipv4_hdr->ip_p = IPPROTO_UDP; + + /* udpյԤͷռ, ٿ */ + memcpy(sock_mbuff->data_actual_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t), sock_rcv_buf, ret); + sock_mbuff->data_actual_len = ret + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t); + + +#if FLWD_NAT_SPORT_VOLATILE + if(memcmp(&local_remote_addr, &g_remote_addr, sizeof(local_remote_addr)) != 0){ + /* ΪNATڲ, ³NATԴ˿ڱ */ + memcpy(&g_remote_addr, &local_remote_addr,sizeof(local_remote_addr)); + } +#endif + + + }else{ + *mbuff = NULL; + return -1; + } + + *mbuff = (void *)sock_mbuff; + + return ret; +} + +void low_level_pkt_free(flwd_device_handle_t *g_dev_handle, int tid, void *mbuff) +{ + socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff; + + free(sock_mbuff->__data_buf); + free(sock_mbuff); + + return; +} + +void *low_level_mbuff_malloc(flwd_device_handle_t *g_dev_handle, int tid, int len) +{ + //flwd_device_handle_socket_t *socket_io_handle = (flwd_device_handle_socket_t *)g_dev_handle->low_level_io_handle; + + socket_mbuff_t *mbuff = (socket_mbuff_t *)malloc(sizeof(socket_mbuff_t)); + + mbuff->__data_buf = (char *)malloc(FLWD_LINK_MTU); + mbuff->data_actual_ptr = mbuff->__data_buf + FLWD_VXLAN_OUTER_PACKET_LEN; + mbuff->__data_buf_max_len = FLWD_LINK_MTU; + mbuff->data_actual_len = 0; + + return (void *)mbuff; +} + +char *low_level_mbuff_mtod(void *mbuff) +{ + socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff; + + return (char *)sock_mbuff->data_actual_ptr; +} + +void low_level_mbuff_free(struct __flwd_device_handle *h, int tid, void *mbuff) +{ + socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff; + + free(sock_mbuff->__data_buf); + sock_mbuff->data_actual_len = 0; + sock_mbuff->__data_buf_max_len = 0; + free(mbuff); +} + +void low_level_mbuff_free_after_send(flwd_device_handle_t *g_dev_handle, int tid, void *mbuff) +{ + /* pcapģʽԶfree, ٴεfree */ + low_level_mbuff_free(g_dev_handle, tid, mbuff); +} + +void low_level_mbuff_send_back(flwd_device_handle_t *g_dev_handle, int tid, void *mbuff) +{ + /* socketģʽʱûעgdevݰ, պ */ + return; +} + +/* + mbuff׷user_data. + return value: + ʼλ; +*/ +char * low_level_mbuff_data_append(void *mbuff, const char *user_data, int user_data_len) +{ + socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff; + + assert(user_data_len <= sock_mbuff->__data_buf_max_len - sock_mbuff->data_actual_len); + + memcpy(sock_mbuff->data_actual_ptr, user_data, user_data_len); + sock_mbuff->data_actual_len += user_data_len; + + return (char *)sock_mbuff->data_actual_ptr; +} + +/* ָǰƶNֽ, ݳԶN, ݰ֮ǰͷ, ԤһЩռ, vxlan */ +char * low_level_mbuff_data_forward(void *mbuff, int n) +{ + socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff; + + assert(n <= sock_mbuff->data_actual_ptr - sock_mbuff->__data_buf); + + sock_mbuff->data_actual_ptr -= n; + sock_mbuff->data_actual_len += n; + + return (char *)sock_mbuff->data_actual_ptr; +} + + +/* ָƶNֽ, ݳԶN, ǰݰijЩͷ, ȥvxlanͷ */ +char * low_level_mbuff_data_rearward(void *mbuff, int n) +{ + socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff; + + assert(n <= sock_mbuff->__data_buf_max_len - sock_mbuff->data_actual_len); + + sock_mbuff->data_actual_ptr += n; + sock_mbuff->data_actual_len -= n; + + return sock_mbuff->data_actual_ptr; +} + + +int low_level_mbuff_get_pkt_len(void *mbuff) +{ + socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff; + + return sock_mbuff->data_actual_len; +} + +void low_level_mbuff_set_pkt_len(void *mbuff, int pkt_len) +{ + socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff; + + sock_mbuff->data_actual_len = pkt_len; +} + + +int low_level_send(flwd_device_handle_t *global_dev_handle, int tid, void *mbuff) +{ + return socket_low_level_send(global_dev_handle, tid, mbuff); +} + + +int low_level_io_init(flwd_device_handle_t *global_dev_handle) +{ + return socket_low_level_io_init(global_dev_handle); +} + +#ifdef __cplusplus +} +#endif + diff --git a/src/packet_io/nf-queue.c b/src/packet_io/nf-queue.c new file mode 100644 index 0000000..c2bc6cc --- /dev/null +++ b/src/packet_io/nf-queue.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +/* only for NFQA_CT, not needed otherwise: */ +#include + +static struct mnl_socket *nl; + +static struct nlmsghdr * +nfq_hdr_put(char *buf, int type, uint32_t queue_num) +{ + struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | type; + nlh->nlmsg_flags = NLM_F_REQUEST; + + struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); + nfg->nfgen_family = AF_UNSPEC; + nfg->version = NFNETLINK_V0; + nfg->res_id = htons(queue_num); + + return nlh; +} + +static void +nfq_send_verdict(int queue_num, uint32_t id) +{ + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + struct nlattr *nest; + + nlh = nfq_hdr_put(buf, NFQNL_MSG_VERDICT, queue_num); + nfq_nlmsg_verdict_put(nlh, id, NF_ACCEPT); + + /* example to set the connmark. First, start NFQA_CT section: */ + nest = mnl_attr_nest_start(nlh, NFQA_CT); + + /* then, add the connmark attribute: */ + mnl_attr_put_u32(nlh, CTA_MARK, htonl(42)); + /* more conntrack attributes, e.g. CTA_LABEL, could be set here */ + + /* end conntrack section */ + mnl_attr_nest_end(nlh, nest); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } +} + +static int queue_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nfqnl_msg_packet_hdr *ph = NULL; + struct nlattr *attr[NFQA_MAX+1] = {}; + uint32_t id = 0, skbinfo; + struct nfgenmsg *nfg; + uint16_t plen; + + if (nfq_nlmsg_parse(nlh, attr) < 0) { + perror("problems parsing"); + return MNL_CB_ERROR; + } + + nfg = mnl_nlmsg_get_payload(nlh); + + if (attr[NFQA_PACKET_HDR] == NULL) { + fputs("metaheader not set\n", stderr); + return MNL_CB_ERROR; + } + + ph = mnl_attr_get_payload(attr[NFQA_PACKET_HDR]); + + plen = mnl_attr_get_payload_len(attr[NFQA_PAYLOAD]); + /* void *payload = mnl_attr_get_payload(attr[NFQA_PAYLOAD]); */ + + skbinfo = attr[NFQA_SKB_INFO] ? ntohl(mnl_attr_get_u32(attr[NFQA_SKB_INFO])) : 0; + + if (attr[NFQA_CAP_LEN]) { + uint32_t orig_len = ntohl(mnl_attr_get_u32(attr[NFQA_CAP_LEN])); + if (orig_len != plen) + printf("truncated "); + } + + if (skbinfo & NFQA_SKB_GSO) + printf("GSO "); + + id = ntohl(ph->packet_id); + printf("packet received (id=%u hw=0x%04x hook=%u, payload len %u", + id, ntohs(ph->hw_protocol), ph->hook, plen); + + /* + * ip/tcp checksums are not yet valid, e.g. due to GRO/GSO. + * The application should behave as if the checksums are correct. + * + * If these packets are later forwarded/sent out, the checksums will + * be corrected by kernel/hardware. + */ + if (skbinfo & NFQA_SKB_CSUMNOTREADY) + printf(", checksum not ready"); + puts(")"); + + nfq_send_verdict(ntohs(nfg->res_id), id); + + return MNL_CB_OK; +} + +int main(int argc, char *argv[]) +{ + char *buf; + /* largest possible packet payload, plus netlink data overhead: */ + size_t sizeof_buf = 0xffff + (MNL_SOCKET_BUFFER_SIZE/2); + struct nlmsghdr *nlh; + int ret; + unsigned int portid, queue_num; + + if (argc != 2) { + printf("Usage: %s [queue_num]\n", argv[0]); + exit(EXIT_FAILURE); + } + queue_num = atoi(argv[1]); + + nl = mnl_socket_open(NETLINK_NETFILTER); + if (nl == NULL) { + perror("mnl_socket_open"); + exit(EXIT_FAILURE); + } + + if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { + perror("mnl_socket_bind"); + exit(EXIT_FAILURE); + } + portid = mnl_socket_get_portid(nl); + + buf = malloc(sizeof_buf); + if (!buf) { + perror("allocate receive buffer"); + exit(EXIT_FAILURE); + } + + /* PF_(UN)BIND is not needed with kernels 3.8 and later */ + nlh = nfq_hdr_put(buf, NFQNL_MSG_CONFIG, 0); + nfq_nlmsg_cfg_put_cmd(nlh, AF_INET, NFQNL_CFG_CMD_PF_UNBIND); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + nlh = nfq_hdr_put(buf, NFQNL_MSG_CONFIG, 0); + nfq_nlmsg_cfg_put_cmd(nlh, AF_INET, NFQNL_CFG_CMD_PF_BIND); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + nlh = nfq_hdr_put(buf, NFQNL_MSG_CONFIG, queue_num); + nfq_nlmsg_cfg_put_cmd(nlh, AF_INET, NFQNL_CFG_CMD_BIND); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + nlh = nfq_hdr_put(buf, NFQNL_MSG_CONFIG, queue_num); + nfq_nlmsg_cfg_put_params(nlh, NFQNL_COPY_PACKET, 0xffff); + + mnl_attr_put_u32(nlh, NFQA_CFG_FLAGS, htonl(NFQA_CFG_F_GSO)); + mnl_attr_put_u32(nlh, NFQA_CFG_MASK, htonl(NFQA_CFG_F_GSO)); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_send"); + exit(EXIT_FAILURE); + } + + /* ENOBUFS is signalled to userspace when packets were lost + * on kernel side. In most cases, userspace isn't interested + * in this information, so turn it off. + */ + ret = 1; + mnl_socket_setsockopt(nl, NETLINK_NO_ENOBUFS, &ret, sizeof(int)); + + for (;;) { + ret = mnl_socket_recvfrom(nl, buf, sizeof_buf); + if (ret == -1) { + perror("mnl_socket_recvfrom"); + exit(EXIT_FAILURE); + } + + ret = mnl_cb_run(buf, ret, 0, portid, queue_cb, NULL); + if (ret < 0){ + perror("mnl_cb_run"); + exit(EXIT_FAILURE); + } + } + + mnl_socket_close(nl); + + return 0; +} diff --git a/src/packet_io/nfq_test.c b/src/packet_io/nfq_test.c new file mode 100644 index 0000000..58e2ee3 --- /dev/null +++ b/src/packet_io/nfq_test.c @@ -0,0 +1,270 @@ +/* + * ===================================================================================== + * + * Filename: nf_queue_test.c + * + * Description: netfilter_queue û̬޸ݰӳ + * + * Version: 1.0 + * Created: 04/02/2010 09:49:48 AM + * Revision: none + * Compiler: gcc + * + * Author: LeiuX (xulei), xulei@pact518.hit.edu.cn + * Company: HIT + * + * ===================================================================================== + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef __LITTLE_ENDIAN +#define IPQUAD(addr) \ +((unsigned char *)&addr)[0], \ +((unsigned char *)&addr)[1], \ +((unsigned char *)&addr)[2], \ +((unsigned char *)&addr)[3] +#else +#define IPQUAD(addr) \ +((unsigned char *)&addr)[3], \ +((unsigned char *)&addr)[2], \ +((unsigned char *)&addr)[1], \ +((unsigned char *)&addr)[0] +#endif + +struct tcp_pseudo /*the tcp pseudo header*/ +{ + __u32 src_addr; + __u32 dst_addr; + __u8 zero; + __u8 proto; + __u16 length; +} pseudohead; + + +long checksum(unsigned short *addr, unsigned int count) { + /* Compute Internet Checksum for "count" bytes + * beginning at location "addr". + */ + register long sum = 0; + + while( count > 1 ) { + /* This is the inner loop */ + sum += * addr++; + count -= 2; + } + /* Add left-over byte, if any */ + if( count > 0 ) + sum += * (unsigned char *) addr; + + /* Fold 32-bit sum to 16 bits */ + while (sum>>16) + sum = (sum & 0xffff) + (sum >> 16); + + return ~sum; +} + + +/*************************tcp checksum**********************/ +long get_tcp_checksum(struct iphdr * myip, struct tcphdr * mytcp) { + + __u16 total_len = ntohs(myip->tot_len); + + int tcpopt_len = mytcp->doff*4 - 20; + int tcpdatalen = total_len - (mytcp->doff*4) - (myip->ihl*4); + + pseudohead.src_addr=myip->saddr; + pseudohead.dst_addr=myip->daddr; + pseudohead.zero=0; + pseudohead.proto=IPPROTO_TCP; + pseudohead.length=htons(sizeof(struct tcphdr) + tcpopt_len + tcpdatalen); + + int totaltcp_len = sizeof(struct tcp_pseudo) + sizeof(struct tcphdr) + tcpopt_len +tcpdatalen; + //unsigned short * tcp = new unsigned short[totaltcp_len]; + + unsigned short * tcp = malloc(totaltcp_len); + + + memcpy((unsigned char *)tcp,&pseudohead,sizeof(struct tcp_pseudo)); + memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo),(unsigned char*)mytcp,sizeof(struct tcphdr)); + memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo)+sizeof(struct tcphdr),(unsigned char *)myip+(myip->ihl*4)+(sizeof(struct tcphdr)), tcpopt_len); + memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo)+sizeof(struct tcphdr)+tcpopt_len, (unsigned char *)mytcp+(mytcp->doff*4), tcpdatalen); + + /* printf("pseud length: %d\n",pseudohead.length); + printf("tcp hdr length: %d\n",mytcp->doff*4); + printf("tcp hdr struct length: %d\n",sizeof(struct tcphdr)); + printf("tcp opt length: %d\n",tcpopt_len); + printf("tcp total+psuedo length: %d\n",totaltcp_len); + + fflush(stdout); + + printf("tcp data len: %d, data start %u\n", tcpdatalen,mytcp + (mytcp->doff*4)); + */ + + + return checksum(tcp,totaltcp_len); + +} + +static u_int16_t tcp_checksum(struct iphdr* iphdrp){ + struct tcphdr *tcphdrp = + (struct tcphdr*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2)); + return get_tcp_checksum(iphdrp, tcphdrp); +} + +static void set_tcp_checksum(struct iphdr* iphdrp){ + struct tcphdr *tcphdrp = + (struct tcphdr*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2)); + tcphdrp->check = 0; + tcphdrp->check = get_tcp_checksum(iphdrp, tcphdrp); +} +/****************************tcp checksum end****************************/ + + +/********************************Ip checksum*****************************/ +static u_int16_t ip_checksum(struct iphdr* iphdrp){ + return checksum((unsigned short*)iphdrp, iphdrp->ihl<<2); +} + +static void set_ip_checksum(struct iphdr* iphdrp){ + iphdrp->check = 0; + iphdrp->check = checksum((unsigned short*)iphdrp, iphdrp->ihl<<2); +} +/****************************Ip checksum end******************************/ + +static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, + struct nfq_data *nfa, void *data){ + (void)nfmsg; + (void)data; + u_int32_t id = 0; + struct nfqnl_msg_packet_hdr *ph; + unsigned char *pdata = NULL; + int pdata_len; + + ph = nfq_get_msg_packet_hdr(nfa); + if (ph){ + id = ntohl(ph->packet_id); + } + + pdata_len = nfq_get_payload(nfa, &pdata); + if(pdata_len == -1){ + pdata_len = 0; + } + + struct iphdr *iphdrp = (struct iphdr *)pdata; + + printf("len %d iphdr %d %u.%u.%u.%u ->", + pdata_len, + iphdrp->ihl<<2, + IPQUAD(iphdrp->saddr)); + printf(" %u.%u.%u.%u %s", + IPQUAD(iphdrp->daddr), + getprotobynumber(iphdrp->protocol)->p_name); + printf(" ipsum %hu", ip_checksum(iphdrp)); + if(iphdrp->protocol == IPPROTO_TCP){ + printf(" tcpsum %hu", tcp_checksum(iphdrp)); + } + + iphdrp->saddr = 0x08080808; + iphdrp->daddr = iphdrp->saddr; + +#if 0 +#define TO "220.181.37.55" +#define DNAT_TO "202.118.236.130" + + if(iphdrp->daddr == inet_addr(TO)){ + printf(" !hacked!"); + iphdrp->daddr = inet_addr(DNAT_TO); + set_ip_checksum(iphdrp); + if(iphdrp->protocol == IPPROTO_TCP){ + set_tcp_checksum(iphdrp); + printf(" ipsum+ %hu tcpsum+ %hu", + ip_checksum(iphdrp), tcp_checksum(iphdrp)); + } + } + + if(iphdrp->saddr == inet_addr(DNAT_TO)){ + iphdrp->saddr = inet_addr(TO); + printf(" !hacked!"); + set_ip_checksum(iphdrp); + if(iphdrp->protocol == IPPROTO_TCP){ + set_tcp_checksum(iphdrp); + printf(" ipsum+ %hu tcpsum+ %hu", + ip_checksum(iphdrp), tcp_checksum(iphdrp)); + } + } +#endif + printf("\n"); + + return nfq_set_verdict_mark(qh, id, NF_REPEAT, 1, (u_int32_t)pdata_len, pdata); +} + +int main(int argc, char **argv) +{ + struct nfq_handle *h; + struct nfq_q_handle *qh; + struct nfnl_handle *nh; + int fd; + int rv; + char buf[4096]; + + h = nfq_open(); + if (!h) { + exit(1); + } + + nfq_unbind_pf(h, AF_INET); + + /*2.6.24 ںBUG nfq_unbind_pf ֵȷ + http://article.gmane.org/gmane.c ... ilter.general/33573*/ + + /* + if (nfq_unbind_pf(h, AF_INET) < 0){ + exit(1); + } + */ + + if (nfq_bind_pf(h, AF_INET) < 0) { + exit(1); + } + + int qid = 0; + if(argc == 2){ + qid = atoi(argv[1]); + } + printf("binding this socket to queue %d\n", qid); + qh = nfq_create_queue(h, qid, &cb, NULL); + if (!qh) { + exit(1); + } + + if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) { + exit(1); + } + + nh = nfq_nfnlh(h); + fd = nfnl_fd(nh); + + while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) { + nfq_handle_packet(h, buf, rv); + } + + /* never reached */ + nfq_destroy_queue(qh); + + nfq_close(h); + + exit(0); +} diff --git a/support/include/MESA_atomic_for_view.h b/support/include/MESA_atomic_for_view.h new file mode 100644 index 0000000..6d8c6ef --- /dev/null +++ b/support/include/MESA_atomic_for_view.h @@ -0,0 +1,38 @@ +#ifndef _MESA_ATOMIC_H_ +#define _MESA_ATOMIC_H_ + + +#if(__GNUC__ * 100 + __GNUC_MINOR__ * 10 + __GNUC_PATCHLEVEL__ >= 411) +typedef unsigned long MESA_ATOMIC_T; +#define MESA_ATOMIC_SET(v, i) __sync_lock_test_and_set((&v), i) +#define MESA_ATOMIC_READ(v) __sync_or_and_fetch((&v), 0) +#define MESA_ATOMIC_INC(v) __sync_add_and_fetch((&v),1) +#define MESA_ATOMIC_DEC(v) __sync_sub_and_fetch((&v),1) +#define MESA_ATOMIC_ADD(v,add) __sync_add_and_fetch((&v),(add)) +#define MESA_ATOMIC_SUB(v,sub) __sync_sub_and_fetch((&v),(sub)) +#else +#include +typedef atomic_t MESA_ATOMIC_T; +#define MESA_ATOMIC_SET(v, i) atomic_set((&v), i) +#define MESA_ATOMIC_READ(v) atomic_read((&v)) +#define MESA_ATOMIC_INC(v) atomic_inc((&v)) +#define MESA_ATOMIC_DEC(v) atomic_dec((&v)) +#define MESA_ATOMIC_ADD(v, add) atomic_add((add),(&v)) +#define MESA_ATOMIC_SUB(v, sub) atomic_sub((sub),(&v)) +#endif + + +#ifdef __tilegx__ +#include +typedef int MESA_ATOMIC_T; +#define MESA_ATOMIC_SET(v, i) arch_atomic_exchange((&v), i) +#define MESA_ATOMIC_READ(v) arch_atomic_or((&v), 0) +#define MESA_ATOMIC_INC(v) arch_atomic_add((&v), 1) +#define MESA_ATOMIC_DEC(v) arch_atomic_sub((&v), 1) +#define MESA_ATOMIC_ADD(v, add) arch_atomic_add((&v), add) +#define MESA_ATOMIC_SUB(v, sub) arch_atomic_sub((&v), sub) +#endif + + +#endif + diff --git a/support/include/MESA_handle_logger_for_view.h b/support/include/MESA_handle_logger_for_view.h new file mode 100644 index 0000000..c615b53 --- /dev/null +++ b/support/include/MESA_handle_logger_for_view.h @@ -0,0 +1,68 @@ +#ifndef MESA_HANDLE__LOGGER_H +#define MESA_HANDLE__LOGGER_H + +/* + * runtime_log with handle, + * based on runtime_log. + * yang wei + * create time:2014-03-24 + * version:20140324 + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define RLOG_LV_DEBUG 10 +#define RLOG_LV_INFO 20 +#define RLOG_LV_FATAL 30 + + +#define MESA_HANDLE_RUNTIME_LOG(handle, lv, mod, fmt, args...) \ + MESA_handle_runtime_log((handle), (lv), (mod), "file %s, line %d, " fmt, \ + __FILE__, __LINE__, ##args) + +/* + * name: MESA_create_runtime_log_handle + * functionality: get runtime_log handle; + * params: + * file_path: path of log file, like "./log/runtime_log"; + * level: level of log; + * returns: + * not NULL, if succeeded; + * NULL, if file is not absolute path, or failed to create log file; + */ +void *MESA_create_runtime_log_handle(const char *file_path, int level); + +/* + * name: MESA_handle_runtime_log + * functionality: appends log message to runtime log file; + * params: + * handle:handle of runtime log, which is created by MESA_create_runtime_log_handle; + * level: log level, messages with level value smaller the global var + * "runtime_log_level" are ignored; + * module: name of loggin module; + * fmt: format string; + * returns: + * none; + */ +void MESA_handle_runtime_log(void *handle, int level, const char *module, const char *fmt, ...); + +/* + * name: MESA_destroy_runtime_log_handle + * functionality: release runtime log handle memory. + * params: + * handle: runtime log handle which is going to be released; + * returns: + * none; + */ +void MESA_destroy_runtime_log_handle(void *handle); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/support/include/MESA_htable_for_view.h b/support/include/MESA_htable_for_view.h new file mode 100644 index 0000000..76d7a2f --- /dev/null +++ b/support/include/MESA_htable_for_view.h @@ -0,0 +1,393 @@ +#ifndef __MESA_HTABLE_H_ +#define __MESA_HTABLE_H_ +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include +#include + +/* + * general purpose hash table implementation. + * + * xiang hong + * 2002-07-28 + *History: + * 2012-03-23 zhengchao add thread safe option and link expire feature; + * 2014-01-27 lijia add reentrant feature. + */ +#define MESA_HTABLE_VERSION_MACRO (20171114) +extern const unsigned int MESA_HTABLE_VERSION_INT; + +#define MESA_HASH_DEBUG (0) + +#define COMPLEX_KEY_SWITCH (1) + +#define ELIMINATE_TYPE_NUM (1) +#define ELIMINATE_TYPE_TIME (2) +#define ELIMINATE_TYPE_MANUAL (3) /* delete oldest item by manual */ + +typedef void * MESA_htable_handle; + + +#define HASH_MALLOC(_n_) malloc(_n_) +#define HASH_FREE(_p_) free(_p_) + + +#ifndef uchar +#define uchar unsigned char +#endif +#ifndef uint +#define uint unsigned int +#endif + +/* eliminate algorithm */ +#define HASH_ELIMINATE_ALGO_FIFO (0) /* by default */ +#define HASH_ELIMINATE_ALGO_LRU (1) + +/* + * hash key compare function prototype, see hash_key_comp(). + * return value: + * 0:key1 and key2 are equal; + * other:key1 and key2 not equal. + */ +typedef int key_comp_fun_t(const uchar * key1, uint size1, const uchar * key2, uint size2); + +/* + * hash key->index computing function prototype, see hash_key2index(). + */ +typedef uint key2index_fun_t(const MESA_htable_handle table, const uchar * key, uint size); + +/* MESA_htable built-in HASH algorithm, MESA_htable use BKDR_hash_algo as default, user can choose any one of the following */ +extern uint BKDR_hash_algo(MESA_htable_handle api_table, const uchar *key, uint size); +extern uint APHash_algo(MESA_htable_handle api_table, const uchar *key, uint size); +extern uint murmur3_32_algo(MESA_htable_handle api_table, const uchar* key, uint size) ; + +typedef void MESA_htable_data_free_cbfun_t(void *data); + +typedef int MESA_htable_expire_notify_cbfun_t(void *data, int eliminate_type); + +typedef uchar* MESA_htable_complex_key_dup_cbfun_t(const uchar *key, uint key_size); + +typedef void MESA_htable_complex_key_free_cbfun_t(uchar *key, uint key_size); + +typedef long hash_cb_fun_t(void *data, const uchar *key, uint size, void *user_arg); + +/* + * thread_safe: 0:create hash table without thread safe features; + * positive:the bigger number has more performance, less collide, but less timeout accuracy. + * max number is 1024. + * recursive: 0:can't recursive call MESA_htable_xxx series function + * 1:can recursive call MESA_htable_xxx series function. + * hash_slot_size: how big do you want the table to be, must be 2^N; + * max_elem_num: the maximum elements of the HASH-table,0 means infinite; + * key_comp: hash key compare function, use default function if NULL; + * suggest implement by yourself. + * key2index: hash key->index computing function, use default function if NULL; + * suggest use MESA_htable built-in function. + * data_free: release resources function; + * data_expire_with_condition: + * if expire_time > 0 and data_expire_with_condition != NULL, + * then call this function when an element expired, and give the reason by the 'type' + * if expire_time > 0 and data_expire_with_condition is NULL, + * eliminate the item immediately; + * args: + * data: pointer to attached data; + * type: item eliminate reason, ELIMINATE_TYPE_NUM or ELIMINATE_TYPE_TIME; + * return value of 'data_expire_with_condition': + * 1: the item can be eliminated; + * 0: the item can't be eliminated, renew the item. + * eliminate_type: the algorithm of elimanate a expired element, 0:FIFO; 1:LRU. + * expire_time: the element expire time in second, 0 means infinite. + */ +typedef struct{ + unsigned int thread_safe; + int recursive; + unsigned int hash_slot_size; + unsigned int max_elem_num; + int eliminate_type; + int expire_time; + key_comp_fun_t * key_comp; + key2index_fun_t * key2index; + void (* data_free)(void *data); + int (*data_expire_with_condition)(void *data, int eliminate_type); +#if COMPLEX_KEY_SWITCH + uchar* (*complex_key_dup)(const uchar *key, uint key_size); + void (* complex_key_free)(uchar *key, uint key_size); +#endif +}MESA_htable_create_args_t; + + +/* All of the following functions return value */ +typedef enum{ + MESA_HTABLE_RET_OK = 0, /* success */ + MESA_HTABLE_RET_COMMON_ERR = -1, /* generalundefined errors */ + MESA_HTABLE_RET_ARG_ERR = -2, /* invalid args */ + MESA_HTABLE_RET_NUM_FULL = -3, /* htable number full */ + MESA_HTABLE_RET_QEMPTY = -4, /* htable empty */ + MESA_HTABLE_RET_DUP_ITEM = -5, /* duplicate item */ + MESA_HTABLE_RET_NOT_FOUND = -6, /* not found item */ + MESA_HTABLE_RET_LEN_ERR = -7, /* length error */ + MESA_HTABLE_RET_CANT_GET_LOCK = -8, /* can't get lock in non-block mode */ + MESA_HTABLE_RET_GET_LOCK_TMOUT = -9, /* get lock timeout */ +}MESA_htable_errno_t; + +/* + * You should never use this API to create a hash table, use MESA_htable_born() instead. + * name: MESA_htable_create + * functionality: allocats memory for hash slots, and initialize hash structure; + * param: + * args: argments set; + * args_len: length of argment set; + * returns: + * NULL : error; + * Non-NULL : success; + */ +MESA_htable_handle MESA_htable_create(const MESA_htable_create_args_t *args, int args_struct_len); + +/* + * get total number of HASH element. +*/ +unsigned int MESA_htable_get_elem_num(const MESA_htable_handle table); + +/* + * name: MESA_htable_destroy + * functionality: cleans up hash structure, frees memory occupied; + * param: + * table: who is the victim; + * func: callback function to clean up data attached to hash items, has higher priority level than MESA_htable_data_free_cbfun_t in initialization. + + * returns: + * always returns 0; + */ +int MESA_htable_destroy(MESA_htable_handle table, void (* func)(void *)); + +/* + * name: MESA_htable_add + * functionality: adds item to table, call hash_expire() if elem_count gets + * bigger than threshold_hi, and adjust threshold; + * param: + * table: to which table do you want to add; + * key: what is the label; + * size: how long is the label; + * data: what data do you want to attach; + * returns: + * >0: success,return hash elems' linklist size; + * 0: success. + * <0: error, refer to MESA_htable_errno_t. + */ +int MESA_htable_add(MESA_htable_handle table, const uchar * key, uint size, const void *data); + + +/* + * name: MESA_htable_del + * functionality: deletes item from table. + * param: + * table: from which table do you want to delete; + * key : what is the label; + * size : how long is the label; + * func : callback function to clean up data attached to hash items, + if this pointer is NULL will call "data_free" in MESA_hash_create(), + * returns: + * 0 : success; + * <0: error, refer to MESA_htable_errno_t. + */ +int MESA_htable_del(MESA_htable_handle table, const uchar * key, uint size, + void (* func)(void *)); +/* + TODO: + MESA_htable_del_with_hash(MESA_htable_handle table, const uchar * key, uint size, uint hash_value, + void (* func)(void *)); + ɾʱ֮ǰhash_value, һhash㿪, +*/ + + +/* + * name: MESA_htable_del_oldest_manual + * functionality: deletes oldest item from table. + * param: + * table: from which table do you want to delete; + * func : callback function to clean up data attached to hash items, + if this pointer is NULL will call "data_free" in MESA_hash_create(), + * batch_num: delete oldest items. + * returns: + * 0, do nothing ; + * >0, delete items; + */ +int MESA_htable_del_oldest_manual(MESA_htable_handle table, void (* func)(void *), int batch_num); + +/* + * name: MESA_htable_search + * functionality: selects item from table; + * param: + * table: from which table do you want to select; + * key : what is the label; + * size : how long is the label; + * + * return: + * not NULL :pointer to attached data; + * NULL :not found(thus be careful if you are attaching NULL data on purpose). + */ +void *MESA_htable_search(const MESA_htable_handle table, const uchar * key, uint size); + +/* + * name: MESA_htable_search_cb + * functionality: selects item from table, and then call 'cb', reentrant; + * in param: + * table: from which table do you want to select; + * key : what is the label; + * size : how long is the label; + * cb : call this function when found the attached data; + * arg : the argument of "cb" function. + * out param: + * cb_ret: the return value of the function "cb". + * return: + * not NULL :pointer to attached data; + * NULL :not found(thus be careful if you are attaching NULL data on purpose). + */ +void *MESA_htable_search_cb(const MESA_htable_handle table, const uchar * key, uint size, + hash_cb_fun_t *cb, void *arg, long *cb_ret); + +/* + * name: MESA_htable_iterate + * functionality: iterates each hash item; + * params: + * table: what table is to be iterated; + * func: what do you want to do to each attached data item; + * returns: + * 0: iterates all items; + * -1: error; + */ +int MESA_htable_iterate(MESA_htable_handle table, + void (* func)(const uchar * key, uint size, void * data, void *user), void * user); + + +/* + * name: MESA_htable_iterate_bytime + * functionality: iterates each hash item by your demand; + * note: + * if 'thread_safe' more than one, this function is not correct. + * params: + * table: what table is to be iterated; + * iterate_type: 1: newest item first; 2: oldest item first; + * iterate_cb: what do you want to do to each attached data item; + * return value of iterate_cb: + * refer to ITERATE_CB_RET_xxx; + * returns: + * 0: iterates all items; + * -1: uncomplete break. + * -2: error; + */ +#define ITERATE_CB_RET_CONTINUE_FLAG (0) /* default, like MESA_htable_iterate() */ +#define ITERATE_CB_RET_BREAK_FLAG (1<<1) /* break iterate, return from MESA_htable_iterate_bytime() immediately */ +#define ITERATE_CB_RET_DEL_FLAG (1<<2) /* del this item, like but faster than call MESA_htable_del() */ +#define ITERATE_CB_RET_REVERSE_FLAG (1<<3) /* if the item is newest item, it will become the oldest item, and vice versa */ +#define ITERATE_CB_RET_REMOVE_BUT_NOT_FREE (1<<4) /* only remove the item from Hash table, but don't free the attached data, be careful */ + +#define ITERATE_TYPE_NEWEST_FIRST (1) +#define ITERATE_TYPE_OLDEST_FIRST (2) +int MESA_htable_iterate_bytime(MESA_htable_handle table, int iterate_type, + int (*iterate_cb)(const uchar * key, uint size, void * data, void *user), void * user); + +/* + args: + print_switch: + 0: disable print message; + 1: enable print message; +*/ +void MESA_htable_print_crtl(MESA_htable_handle table, int print_switch); + + +/* + Create a htable handle and Alloc memory, and set default option, + but can't running before call MESA_htable_mature(). + + return value: + not NULL: success. + NULL : error. +*/ +MESA_htable_handle MESA_htable_born(void); + +/* + MESA_htable option definition. +*/ +enum MESA_htable_opt{ + MHO_THREAD_SAFE = 0, /* must be int, 1:create hash table with thread safe features, default is 0 */ + MHO_MUTEX_NUM, /* must be int, valid only if MHO_THREAD_SAFE is not zero, max value is 1024, defalut is 1. the bigger number has more performance and less mutex collide, but less timeout accuracy */ + MHO_HASH_SLOT_SIZE, /* must be unsigned int, default is 1048576. */ + MHO_HASH_MAX_ELEMENT_NUM, /* must be unsigned int, defalut is 0, means infinite */ + MHO_EXPIRE_TIME, /* must be int, defalut is 0, means infinite */ + MHO_ELIMIMINATE_TYPE, /* must be int, valid only if MHO_EXPIRE_TIME is not zero. HASH_ELIMINATE_ALGO_FIFO or HASH_ELIMINATE_ALGO_LRU, defalut HASH_ELIMINATE_ALGO_FIFO */ + MHO_CBFUN_KEY_COMPARE, /* must be key_comp_fun_t, hash key compare function, use default function if NULL */ + MHO_CBFUN_KEY_TO_INDEX, /* must be key2index_fun_t, hash key->index computing function, use default function if NULL */ + MHO_CBFUN_DATA_FREE, /* must be MESA_htable_data_free_cbfun_t, release resources function */ + /* data_expire_notify, must be MESA_htable_expire_notify_cbfun_t, + * if expire_time > 0 and data_expire_notify != NULL, + * then call this function when an element expired, and give the reason by the 'type' + * if expire_time > 0 and data_expire_notify is NULL, + * eliminate the item immediately; + * args: + * data: pointer to attached data; + * type: item eliminate reason, ELIMINATE_TYPE_NUM or ELIMINATE_TYPE_TIME; + * return value of 'data_expire_with_condition': + * 1: the item can be eliminated; + * 0: the item can't be eliminated, renew the item. + */ + MHO_CBFUN_DATA_EXPIRE_NOTIFY, + MHO_CBFUN_COMPLEX_KEY_DUP, /* must be MESA_htable_complex_key_dup_cbfun_t, if key store in a complex struct, caller must be implement this duplicate function. */ + MHO_CBFUN_COMPLEX_KEY_FREE, /* must be MESA_htable_complex_key_free_cbfun_t, if key store in a complex struct, caller must be implement this duplicate function. */ + MHO_AUTO_UPDATE_TIME, /* must be int, create a background thread used to update current_time instead of time(NULL). 1:enable; 0:disable; default value is 0; */ + MHO_SCREEN_PRINT_CTRL, /* must be int, 1:enable screen print; 0:disable screen print; default is 1. */ + MHO_HASH_LIST_COLLIDE_THRESHOLD, /* must be int, write log when hash collide number more than this, default is 100, 0 means infinite. */ + MHO_HASH_LOG_FILE, /* must be char * with EOF, default is "./log/htable_runtime_%p_%t.log", opt_len is strlen(optval) */ + MHO_HASH_SEARCH_MAX_TIMES, /* must be int, max compare items in once MESA_htable_search() */ + MHO_HASH_SEARCH_AVG_TIMES, /* must be double, average compare items in all previous MESA_htable_search() */ + MHO_AUTO_EXPAND_MULTIPLE, /* must be int, default is 0, if this option value bigger than zero, user should set small SLOT_SIZE in initialization for economize memory, htable will auto expand SLOT_SIZE if hash collide item number more than MHO_HASH_LIST_COLLIDE_THRESHOLD. */ + __MHO_MAX_VAL, /* caller can't use this definition, it's value maybe changed in next version!! */ +}; + + +/* + to set features of specified MESA_htable handle. + opt_type: option type, refer to enum MESA_htable_opt; + opt_val : option value, depend on opt type; + opt_len : opt_val size, depend on opt type; + + return value: + 0 :success; + <0:error; +*/ +int MESA_htable_set_opt(MESA_htable_handle table, enum MESA_htable_opt opt_type, void *opt_val, int opt_len); + +/* + to get features of specified MESA_htable handle. + opt_type: option type, refer to enum MESA_htable_opt; + opt_val : option value, depend on opt type; + opt_len : value-result argument, opt_val size, depend on opt type; + + return value: + 0 :success; + <0:error; +*/ +int MESA_htable_get_opt(MESA_htable_handle api_table, enum MESA_htable_opt opt_type, void *opt_val, int *opt_len); + +/* + Construct htable and ready to running. + + return value: + 0 : success; + <0: error. +*/ +int MESA_htable_mature(MESA_htable_handle table); + + +#ifdef __cplusplus +} +#endif + +#endif /* _LIB_HASH_H_INCLUDED_ */ + + diff --git a/support/include/MESA_list_count_for_view.h b/support/include/MESA_list_count_for_view.h new file mode 100644 index 0000000..55523aa --- /dev/null +++ b/support/include/MESA_list_count_for_view.h @@ -0,0 +1,31 @@ +#ifndef _MESA_LIST_COUNT_H_ +#define _MESA_LIST_COUNT_H_ + +typedef struct MESA_list_count{ + struct MESA_list_count *nextele; + struct MESA_list_count *preele; + void *quiddity; +}MESA_list_count_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +void MESA_list_count_init_head(struct MESA_list_count *head); +long MESA_list_count_get_count(const struct MESA_list_count *head); +int MESA_list_count_is_empty(const struct MESA_list_count *head); +void MESA_list_count_add(struct MESA_list_count *head, struct MESA_list_count *new_list); +void MESA_list_count_add_tail(struct MESA_list_count *head, struct MESA_list_count *new_list); +void MESA_list_count_del(struct MESA_list_count *head, struct MESA_list_count *del_list); +void MESA_list_count_move(struct MESA_list_count *head, struct MESA_list_count *list); +void MESA_list_count_move_tail(struct MESA_list_count *head, struct MESA_list_count *list); +struct MESA_list_count *MESA_list_count_join_n(struct MESA_list_count *head, struct MESA_list_count *op_place, struct MESA_list_count *new_obj); +struct MESA_list_count *MESA_list_count_join_p(struct MESA_list_count *head, struct MESA_list_count *new_obj, struct MESA_list_count *op_place); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/support/include/MESA_list_for_view.h b/support/include/MESA_list_for_view.h new file mode 100644 index 0000000..6d7cee8 --- /dev/null +++ b/support/include/MESA_list_for_view.h @@ -0,0 +1,34 @@ +#ifndef _MESA_LIST_H_ +#define _MESA_LIST_H_ + +typedef struct MESA_list{ + struct MESA_list *nextele; + struct MESA_list *preele; + void *quiddity; +}MESA_list_t; + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define MESA_LIST_VERSION_MACRO (20150529) +extern const unsigned int MESA_LIST_VERSION_INT; + +void MESA_list_init_head(struct MESA_list *head); +int MESA_list_is_empty(const struct MESA_list *head); +void MESA_list_add(struct MESA_list *head, struct MESA_list *new_list); +void MESA_list_add_tail(struct MESA_list *head, struct MESA_list *new_list); +void MESA_list_del(struct MESA_list *head, struct MESA_list *del_list); +void MESA_list_move(struct MESA_list *head, struct MESA_list *list); +void MESA_list_move_tail(struct MESA_list *head, struct MESA_list *list); +struct MESA_list *MESA_list_join_n(struct MESA_list *head, struct MESA_list *op_place, struct MESA_list *new_obj); +struct MESA_list *MESA_list_join_p(struct MESA_list *head, struct MESA_list *new_obj, struct MESA_list *op_place); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/support/include/MESA_list_queue_for_view.h b/support/include/MESA_list_queue_for_view.h new file mode 100644 index 0000000..6fdbdd7 --- /dev/null +++ b/support/include/MESA_list_queue_for_view.h @@ -0,0 +1,115 @@ +#ifndef _MESA_LIST_QUEUE_H_ +#define _MESA_LIST_QUEUE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + MESA_list 棬 + 1-̰߳ȫ; + 2-ڲṹ, ȫӿڸ; + 3-йڵṹʹø; +*/ + +#define MESA_LIST_QUEUE_VERSION_MACRO (20160308) +extern const unsigned int MESA_LIST_QUEUE_VERSION_INT; + +#define MESA_LIST_OP_PLACE_HEAD (0x1) +#define MESA_LIST_OP_PLACE_TAIL (0x2) + +#define MESA_list_GET (0x1) +#define MESA_list_JOIN (0x2) + +#define MESA_list_BOLCK (0x4) +#define MESA_list_NONBOLCK (0x8) + +#define MESA_list_JOIN_BLOCK (MESA_list_JOIN|MESA_list_BOLCK) +#define MESA_list_JOIN_NONBLOCK (MESA_list_JOIN|MESA_list_NONBOLCK) +#define MESA_list_GET_BLOCK (MESA_list_GET|MESA_list_BOLCK) +#define MESA_list_GET_NONBLOCK (MESA_list_GET|MESA_list_NONBOLCK) + +typedef void * MESA_lqueue_head; +typedef int (* MESA_lqueue_cb_t)(void *data, long data_len, void *arg); + +/* All of the following functions return value */ +typedef enum{ + MESA_QUEUE_RET_OK = 0, /* success */ + MESA_QUEUE_RET_COMMON_ERR = -1, /* generalundefined errors */ + MESA_QUEUE_RET_ARG_ERR = -2, /* invalid args */ + MESA_QUEUE_RET_NUM_FULL = -3, /* queue number full */ + MESA_QUEUE_RET_MEM_FULL = -4, /* queue memory full */ + MESA_QUEUE_RET_QEMPTY = -5, /* queue empty */ + MESA_QUEUE_RET_LEN_ERR = -6, /* length error */ + MESA_QUEUE_RET_CANT_GET_LOCK = -7, /* can't get lock in non-block mode */ + MESA_QUEUE_RET_GET_LOCK_TMOUT = -8, /* get lock timeout */ +}MESA_queue_errno_t; + +/* + args description: + [IN] + thread_safe : 1:create thread safe queue; 0:without thread safe insurance. + max_item_num: maximum queue items of the queue, 0 means infinity. +*/ +MESA_lqueue_head MESA_lqueue_create(int thread_safe, long max_item_num); + +/* + attention: + The follow two functions is get some value of queue in a moment, + however, the value you got is not exactly, + because it's maybe changed immediately by other thread when this functions is return. +*/ +long MESA_lqueue_get_mem_used(MESA_lqueue_head head); +long MESA_lqueue_get_count(MESA_lqueue_head head); + + +/* + args description: + [IN]: + lq_head : the handler of MESA_lqueue. + + [OUT]: + data : receive buffer. + + [IN && OUT]: + data_len: + is value-result argument, like "addrlen of recvfrom(2)", + the caller should initialize the size of the 'data', + will modified on return to indicate the actual size of the queue item. + +*/ +int MESA_lqueue_read_head(MESA_lqueue_head lq_head, void *data, long *data_len); +int MESA_lqueue_get_head(MESA_lqueue_head lqhead, void *data, long *data_len); + +/* + if return value of "cb" is 0, the behaviour is like MESA_lqueue_read_head(), + else if return value of "cb" is not 0, the behaviour is like MESA_lqueue_get_head(). +*/ +int MESA_lqueue_detect_get_head(MESA_lqueue_head lq_head, MESA_lqueue_cb_t cb, void *data, long *data_len, void *cb_arg); +int MESA_lqueue_get_tail(MESA_lqueue_head lq_head, void *data, long *data_len); + +int MESA_lqueue_join_head(MESA_lqueue_head lq_head, const void *data, long data_len); +int MESA_lqueue_join_tail(MESA_lqueue_head lq_head, const void *data, long data_len); + + +/* these functions features same with above no "try", + except shall return immediately, in other word is "Non-block mode"! + */ +int MESA_lqueue_try_read_head(MESA_lqueue_head lq_head, void *data, long *data_len); +int MESA_lqueue_try_get_head(MESA_lqueue_head lq_head, void *data, long *data_len); +int MESA_lqueue_try_get_tail(MESA_lqueue_head lq_head, void *data, long *data_len); +int MESA_lqueue_try_join_head(MESA_lqueue_head lq_head, const void *data, long data_len); +int MESA_lqueue_try_join_tail(MESA_lqueue_head lq_head, const void *data, long data_len); + + +void MESA_lqueue_destroy(MESA_lqueue_head head, MESA_lqueue_cb_t cb, void *cb_arg); + +const char *MESA_lqueue_strerror(MESA_queue_errno_t error_num); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/support/include/MESA_prof_load_for_view.h b/support/include/MESA_prof_load_for_view.h new file mode 100644 index 0000000..9ed5b40 --- /dev/null +++ b/support/include/MESA_prof_load_for_view.h @@ -0,0 +1,179 @@ +#ifndef SLIB_LOADPROF_H +#define SLIB_LOADPROF_H +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +// Read in specified integer value +// +// Return: +// 0 : success +// < 0 : error, val is set to default +int MESA_load_profile_int_def( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + int *val, // [OUT] returned value + const int dval); // [IN] default value + + + +// Read in specified integer value +// +// Return: +// 0 : success +// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error +// -2 : error ,the val if out of range +int MESA_load_profile_int_nodef( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + int *val); // [OUT] returned value + + + + +// Read in specified unsigned integer value +// +// Return: +// 0 : success +// < 0 : error, val is set to default +int MESA_load_profile_uint_def( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + unsigned int *val, // [OUT] returned value + const unsigned int dval); // [IN] default value + + + +// Read in specified unsigned integer value +// +// Return: +// 0 : success +// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error +// -2 : error ,the val if out of range +int MESA_load_profile_uint_nodef( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + unsigned int *val); // [OUT] returned value + + + +// Read in specified short integer value +// +// Return: +// 0 : success +// < 0 : error, val is set to default +int MESA_load_profile_short_def( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + short *val, // [OUT] returned value + const short dval); // [IN] default value + + + +// Read in specified short integer value +// +// Return: +// 0 : success +// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error +// -2 : error ,the val if out of range +int MESA_load_profile_short_nodef( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + short *val); // [OUT] returned value + + + +// Read in specified string value, +// if value string is too long to return, extra chars truncated. +// prefix/postfix space chars cutted, +// space chars: ' ', '\t' '\n' '\r' +// +// Return: +// >= 0 : length of val +// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error + +int MESA_load_profile_string_nodef( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + char *str, // [OUT] returned string + const size_t size); // [IN] buffer size(bytes) + + + +// Read in specified string value, +// if value string is too long to return, extra chars truncated. +// prefix/postfix space chars cutted, +// space chars: ' ', '\t' '\n' '\r' +// +// Return: +// >= 0 : length of val +// < 0 : error, str is set to default +int MESA_load_profile_string_def( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + char *str, // [OUT] returned string + const size_t size, // [IN] buffer size(bytes) + const char *dstr); // [IN] default string + + + +//read ips from config file +//return : +// >=0 : success,return the number of ip read from file successfully +// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error +// -2 : error,invalid ip + +//if 0 +int MESA_load_profile_ipset( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + const size_t size, // [IN] the size of memory ips point,it must equel or greater than ip_num*sizeof(unsigned int) + unsigned int *ipset); // [OUT] return ipset network bytes order + +// Write the a int into specified position of the config file,the position is decided by section and key +// Return: +// >= 0 : success +// -1 : failed to write profile,maybe fopen failed, or malloc failed +int MESA_write_profile_int( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + const int value); // [IN] the integer need write + +// Write the a float into specified position of the config file,the position is decided by section and key +// Return: +// >= 0 : success +// -1 : failed to write profile,maybe fopen failed, or malloc failed +int MESA_write_profile_float( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + const float value); // [IN] the float need write + +// Write the a string into specified position of the config file,the position is decided by section and key +// Return: +// >= 0 : success +// -1 : failed to write profile,maybe fopen failed, or malloc failed +int MESA_write_profile_string( + const char *file, // [IN] initialization file path + const char *section, // [IN] section name in initialization file + const char *key, // [IN] keyword name in initialization file + const char *value); // [IN] the string need write +//endif +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef SLIB_LOADPROF_H */ diff --git a/support/include/MESA_ring_queue_for_view.h b/support/include/MESA_ring_queue_for_view.h new file mode 100644 index 0000000..cc1efe8 --- /dev/null +++ b/support/include/MESA_ring_queue_for_view.h @@ -0,0 +1,107 @@ +#ifndef __MESA_RING_QUEUE_H_ +#define __MESA_RING_QUEUE_H_ 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef void * MESA_ring_queue_head; + +#define MESA_RING_QUEUE_VERSION_MACRO (20160708) +extern const unsigned int MESA_RING_QUEUE_VERSION_INT; + +/* All of the following functions return value */ +typedef enum{ + MESA_RQUEUE_RET_OK = 0, /* success */ + MESA_RQUEUE_RET_COMMON_ERR = -1, /* generalundefined errors */ + MESA_RQUEUE_RET_ARG_ERR = -2, /* invalid args */ + MESA_RQUEUE_RET_NUM_FULL = -3, /* queue number full */ + MESA_RQUEUE_RET_MEM_FULL = -4, /* queue memory full */ + MESA_RQUEUE_RET_QEMPTY = -5, /* queue empty */ + MESA_RQUEUE_RET_LEN_ERR = -6, /* length error */ + MESA_RQUEUE_RET_CANT_GET_LOCK = -7, /* can't get lock in non-block mode */ + MESA_RQUEUE_RET_GET_LOCK_TMOUT = -8, /* get lock timeout */ +}MESA_ring_queue_errno_t; + + +/* + args description: + [IN] + thread_safe : 1:create thread safe queue; 0:without thread safe insurance. + max_item_num: maximum queue items of the queue, must more than zero. +*/ +MESA_ring_queue_head MESA_ring_queue_born(void); + + +enum MESA_rq_opt{ + RQO_THREAD_SAFE = 0, /* must be int, 1:create ring qqueue with thread safe features, default is 1 */ + RQO_RING_ELEMENT_NUM, /* must be unsigned int, defalut is 1000. */ + RQO_PRE_ALLOC_BUF_LEN, /* must be unsigned int, Ԥȷÿitemڴ, Ժֻmemcpy */ + RQO_MULTI_THREAD_LOCK_FREE, /* must be int, default is 0, conflict with RQO_THREAD_SAFE */ +}; + +/* + to set features of specified MESA_ring_queue_headhandle. + opt_type: option type, refer to enum MESA_htable_opt; + opt_val : option value, depend on opt type; + opt_len : opt_val size, depend on opt type; + + return value: + 0 :success; + <0:error; +*/ +int MESA_ring_queue_set_opt(MESA_ring_queue_head rq, enum MESA_rq_opt opt_type, void *opt_val, int opt_len); + + +/* + Construct ring queue and ready to running. + + return value: + 0 : success; + <0: error. +*/ +int MESA_ring_queue_mature(MESA_ring_queue_head rq); + + + +int MESA_ring_queue_get_count(MESA_ring_queue_head head); + +/* + args description: + [IN]: + lq_head : the handler of MESA_ring_queue. + + [OUT]: + data : receive buffer. + + [IN && OUT]: + data_len: + is value-result argument, like "addrlen of recvfrom(2)", + the caller should initialize the size of the 'data', + will modified on return to indicate the actual size of the queue item. + +*/ +int MESA_ring_queue_read(MESA_ring_queue_head rq_head, void *data, int *data_len); +int MESA_ring_queue_get(MESA_ring_queue_head rqhead, void *data, int *data_len); +int MESA_ring_queue_join(MESA_ring_queue_head rq_head, const void *data, int data_len); + + +/* these functions features same with above no "try", + except shall return immediately, in other word is "Non-block mode"! + */ +int MESA_ring_queue_try_read(MESA_ring_queue_head rq_head, void *data, int *data_len); +int MESA_ring_queue_try_get(MESA_ring_queue_head rqhead, void *data, int *data_len); +int MESA_ring_queue_try_join(MESA_ring_queue_head rq_head, const void *data, int data_len); + + +typedef int (* MESA_rqueue_cb_t)(void *data, long data_len, void *arg); +void MESA_ring_queue_destroy(MESA_ring_queue_head rq_head, MESA_rqueue_cb_t cb, void *cb_arg); +const char *MESA_ring_queue_strerror(MESA_ring_queue_errno_t error_num); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/support/include/Maat_command_for_view.h b/support/include/Maat_command_for_view.h new file mode 100644 index 0000000..1d65383 --- /dev/null +++ b/support/include/Maat_command_for_view.h @@ -0,0 +1,154 @@ +#ifndef H_MAAT_COMMAND_H_INCLUDE +#define H_MAAT_COMMAND_H_INCLUDE +#ifndef __cplusplus +#error("This file should be compiled with C++ compiler") +#endif +#include "Maat_rule.h" +enum MAAT_OPERATION +{ + MAAT_OP_DEL=0, + MAAT_OP_ADD +}; + +enum MAAT_REGION_TYPE +{ + REGION_EXPR, + REGION_IP, + REGION_INTERVAL, + REGION_DIGEST, + REGION_SIMILARITY +}; +enum MAAT_EXPR_TYPE +{ + EXPR_TYPE_STRING=0, + EXPR_TYPE_AND, + EXPR_TYPE_REGEX, + EXPR_TYPE_OFFSET +}; +enum MAAT_MATCH_METHOD +{ + MATCH_METHOD_SUB=0, + MATCH_METHOD_RIGHT, + MATCH_METHOD_LEFT, + MATCH_METHOD_COMPLETE +}; + +enum MAAT_CASE_TYPE +{ + UNCASE_PLAIN=0, + CASE_HEXBIN, + CASE_PLAIN +}; +enum MAAT_ADDR_TYPE +{ + ADDR_TYPE_IPv4=4, + ADDR_TYPE_IPv6=6 +}; +enum MAAT_ADDR_DIRECTION +{ + ADDR_DIR_DOUBLE=0, + ADDR_DIR_SINGLE=1 +}; +struct Maat_rgn_str_t +{ + const char *keywords; + const char *district;// optional for expr_plus, otherwise set to NULL. + enum MAAT_EXPR_TYPE expr_type; + enum MAAT_MATCH_METHOD match_method; + enum MAAT_CASE_TYPE hex_bin; +}; +struct Maat_rgn_addr_t +{ + enum MAAT_ADDR_TYPE addr_type; + const char* src_ip; + const char* mask_src_ip; + const char* dst_ip; + const char* mask_dst_ip; + unsigned short src_port; + unsigned short mask_src_port; + unsigned short dst_port; + unsigned short mask_dst_port; + unsigned short protocol; + enum MAAT_ADDR_DIRECTION direction; +}; +struct Maat_rgn_intv_t +{ + unsigned int low_boundary; + unsigned int up_boundary; +}; +struct Maat_rgn_digest_t +{ + unsigned long long orgin_len; + const char* digest_string; + short confidence_degree; +}; +struct Maat_rgn_sim_t +{ + char* target; + short threshold;// 1~100 +}; +struct Maat_region_t +{ + const char* table_name; + int region_id; //If MAAT_OPT_CMD_AUTO_NUMBERING==1, maat will assigned one. Or users must appoint a unique number. + enum MAAT_REGION_TYPE region_type; + union + { + struct Maat_rgn_str_t expr_rule; + struct Maat_rgn_addr_t ip_rule; + struct Maat_rgn_intv_t interval_rule; + struct Maat_rgn_digest_t digest_rule; + struct Maat_rgn_sim_t similarity_rule; + }; +}; +struct Maat_group_t +{ + int region_num; + int group_id; //If MAAT_OPT_CMD_AUTO_NUMBERING==1, maat will assigned one. Or users must assign a unique number. + struct Maat_region_t *regions; +}; +struct Maat_cmd_t +{ + struct Maat_rule_t compile; // for MAAT_OP_DEL, only compile.config_id is necessary. + int group_num; // for MAAT_OP_DEL, set to 0. + int expire_after; //expired after $expire_after$ seconds, set to 0 for never timeout. + int label_id; //>0, to be indexed and quried by Maat_cmd_select; =0 not index + struct Maat_group_t* groups;// Add regions with Maat_add_region2cmd +}; +struct Maat_line_t +{ + const char* table_name; + const char* table_line; + int rule_id; // for MAAT_OP_DEL, only rule_id is necessary. + int label_id; + int expire_after; //expired after $timeout$ seconds, set to 0 for never timeout. +}; +struct Maat_cmd_t* Maat_create_cmd(const struct Maat_rule_t* rule, int group_num); +//input: which_group 0~group_num +//input: region can be freed after added. +void Maat_add_region2cmd(struct Maat_cmd_t* cmd,int which_group,const struct Maat_region_t* region); + +void Maat_free_cmd(struct Maat_cmd_t* cmd); +int Maat_format_cmd(struct Maat_cmd_t* cmd, char* buffer, int size); +// REGION_EXPR and REGION_SIMILARITY need to escape input string. +char* Maat_str_escape(char* dst,int size,const char*src); + +//Deletion failed due to not complete synchronize with Redis. +//To make sure the delete command is excecuted, user should try again after MAAT_OPT_SCANDIR_INTERVAL_MS ms. +// The following functions are NOT thread safe. +int Maat_cmd(Maat_feather_t feather,struct Maat_cmd_t* cmd,enum MAAT_OPERATION op); + +//pipeline model +int Maat_cmd_append(Maat_feather_t feather,struct Maat_cmd_t* cmd,enum MAAT_OPERATION op); +int Maat_cmd_commit(Maat_feather_t feather); + + +int Maat_cmd_set_group(Maat_feather_t feather, int group_id, const struct Maat_region_t* region, enum MAAT_OPERATION op); +int Maat_cmd_set_line(Maat_feather_t feather,const struct Maat_line_t* line_rule, enum MAAT_OPERATION op); + +//Return the value of key after the increment. +//If the key does not exist, it is set to 0 before performing the operation. +long long Maat_cmd_incrby(Maat_feather_t feather,const char* key, int increment); +int Maat_cmd_select(Maat_feather_t feather, int label_id, int * output_ids, unsigned int size); +#endif + diff --git a/support/include/Maat_rule_for_view.h b/support/include/Maat_rule_for_view.h new file mode 100644 index 0000000..e160a4a --- /dev/null +++ b/support/include/Maat_rule_for_view.h @@ -0,0 +1,228 @@ + +/* +*****************Maat Network Flow Rule Manage Framework******** +* Maat is the Goddess of truth and justice in ancient Egyptian concept. +* Her feather was the measure that determined whether the souls (considered +* to reside in the heart) of the departed would reach the paradise of afterlife +* successfully. +* Author: zhengchao@iie.ac.cn,MESA +* Version 2015-11-09 digest scan +* NOTE: MUST compile with G++ +* All right reserved by Institute of Infomation Engineering,Chinese Academic of Science 2014~2018 +********************************************************* +*/ +#ifndef H_MAAT_RULE_H_INCLUDE +#define H_MAAT_RULE_H_INCLUDE +#ifndef __cplusplus +#error("This file should be compiled with C++ compiler") +#endif +#include "stream.h" +enum MAAT_CHARSET +{ + CHARSET_NONE=0, + CHARSET_GBK, + CHARSET_BIG5, + CHARSET_UNICODE, + CHARSET_UTF8, // 4 + CHARSET_BIN, //5 + CHARSET_UNICODE_ASCII_ESC, // Unicode Escape format, prefix backslash-u hex, e.g. "\u627;" + CHARSET_UNICODE_ASCII_ALIGNED,//Unicode Escape format, prefix backslash-u with 4 bytes aligned, e.g. "\u0627" + CHARSET_UNICODE_NCR_DEC, //SGML Numeric character reference,decimal base, e.g. "ا" + CHARSET_UNICODE_NCR_HEX, //SGML Numeric character reference,hexdecimal base, e.g. "ا" + CHARSET_URL_ENCODE_GB2312, //URL encode with GB2312, e.g. the chinese word "china" was encoded to %D6%D0%B9%FA + CHARSET_URL_ENCODE_UTF8 //11, URL encode with UTF8,e.g. the chinese word "china" was encoded to %E4%B8%AD%E5%9B%BD +}; +enum MAAT_ACTION +{ + MAAT_ACTION_BLOCK=0, + MAAT_ACTION_MONIT, + MAAT_ACTION_WHITE +}; +enum MAAT_POS_TYPE +{ + MAAT_POSTYPE_EXPR=0, + MAAT_POSTYPE_REGEX +}; +typedef void* scan_status_t; +typedef void* stream_para_t; +typedef void* Maat_feather_t; + + +#define MAX_SERVICE_DEFINE_LEN 128 +struct Maat_rule_t +{ + int config_id; + int service_id; + char do_log; + char do_blacklist; + char action; + char resevered; + int serv_def_len; + char service_defined[MAX_SERVICE_DEFINE_LEN]; +}; +#define MAAT_RULE_UPDATE_TYPE_FULL 1 +#define MAAT_RULE_UPDATE_TYPE_INC 2 +typedef void Maat_start_callback_t(int update_type,void* u_para); +typedef void Maat_update_callback_t(int table_id,const char* table_line,void* u_para); +typedef void Maat_finish_callback_t(void* u_para); + + + + + +//--------------------HITTING DETAIL DESCRIPTION BEGIN + +#define MAAT_MAX_HIT_RULE_NUM 8 +#define MAAT_MAX_EXPR_ITEM_NUM 8 +#define MAAT_MAX_HIT_POS_NUM 8 +#define MAAT_MAX_REGEX_GROUP_NUM 8 + +//NOTE position buffer as hitting_regex_pos and hit_pos,are ONLY valid before next scan or Maat_stream_scan_string_end +struct regex_pos_t +{ + int group_num; + int hitting_regex_len; + const char* hitting_regex_pos; + int grouping_len[MAAT_MAX_REGEX_GROUP_NUM]; + const char* grouping_pos[MAAT_MAX_REGEX_GROUP_NUM]; +}; +struct str_pos_t +{ + int hit_len; + const char* hit_pos; +}; +struct sub_item_pos_t +{ + enum MAAT_POS_TYPE ruletype; + int hit_cnt; + union + { + struct regex_pos_t regex_pos[MAAT_MAX_HIT_POS_NUM]; + struct str_pos_t substr_pos[MAAT_MAX_HIT_POS_NUM]; + }; +}; + +struct Maat_region_pos_t +{ + + int region_id; + int sub_item_num; + struct sub_item_pos_t sub_item_pos[MAAT_MAX_EXPR_ITEM_NUM]; +}; + +struct Maat_hit_detail_t +{ + int config_id;//set <0 if half hit; + int hit_region_cnt; + struct Maat_region_pos_t region_pos[MAAT_MAX_HIT_RULE_NUM]; +}; +//--------------------HITTING DETAIL DESCRIPTION END + +//Abondon interface ,left for compatible. +Maat_feather_t Maat_summon_feather(int max_thread_num, + const char* table_info_path, + const char* ful_cfg_dir, + const char* inc_cfg_dir, + void*logger);//MESA_handle_logger +//Abondon interface ,left for compatible. +Maat_feather_t Maat_summon_feather_json(int max_thread_num, + const char* table_info_path, + const char* json_rule, + void* logger); + +Maat_feather_t Maat_feather(int max_thread_num,const char* table_info_path,void* logger); +int Maat_initiate_feather(Maat_feather_t feather); + +enum MAAT_INIT_OPT +{ + MAAT_OPT_SCANDIR_INTERVAL_MS=1, //VALUE is interger, SIZE=sizeof(int). DEFAULT:1,000 milliseconds. + MAAT_OPT_EFFECT_INVERVAL_MS, //VALUE is interger, SIZE=sizeof(int). DEFAULT:60,000 milliseconds. + MAAT_OPT_FULL_CFG_DIR, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1.DEFAULT: no default. + MAAT_OPT_INC_CFG_DIR, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1.DEFAULT: no default. + MAAT_OPT_JSON_FILE_PATH, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1.DEFAULT: no default. + MAAT_OPT_STAT_ON, //VALUE is NULL,SIZE is 0. MAAT_OPT_STAT_FILE_PATH must be set. Default: stat OFF. + MAAT_OPT_PERF_ON, //VALUE is NULL,SIZE is 0. MAAT_OPT_STAT_FILE_PATH must be set. Default: stat OFF. + MAAT_OPT_STAT_FILE_PATH, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. DEFAULT: no default. + MAAT_OPT_SCAN_DETAIL, //VALUE is interger *, SIZE=sizeof(int). 0: not return any detail;1: return hit pos, not include regex grouping; + // 2 return hit pos and regex grouping pos;DEFAULT:0 + MAAT_OPT_INSTANCE_NAME, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1, no more than 11 bytes.DEFAULT: MAAT_$tableinfo_path$. + MAAT_OPT_DECRYPT_KEY, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. No DEFAULT. + MAAT_OPT_REDIS_IP, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. No DEFAULT. + MAAT_OPT_REDIS_PORT, //VALUE is a unsigned short, host order, SIZE= sizeof(unsigned short). No DEFAULT. + MAAT_OPT_REDIS_INDEX, //VALUE is interger *, 0~15, SIZE=sizeof(int). DEFAULT: 0. + MAAT_OPT_CMD_AUTO_NUMBERING, //VALUE is interger *, 1 or 0, SIZE=sizeof(int). DEFAULT: 1. + MAAT_OPT_DEFERRED_LOAD //VALUE is NULL,SIZE is 0. Default: Deffered initialization OFF. +}; +//return -1 if failed, return 0 on success; +int Maat_set_feather_opt(Maat_feather_t feather,enum MAAT_INIT_OPT type,const void* value,int size); +void Maat_burn_feather(Maat_feather_t feather); + +//return table_id(>=0) if success,otherwise return -1; +int Maat_table_register(Maat_feather_t feather,const char* table_name); +//return 1 if success,otherwise return -1 incase invalid table_id or registed function number exceed 32; +int Maat_table_callback_register(Maat_feather_t feather,short table_id, + Maat_start_callback_t *start,//MAAT_RULE_UPDATE_TYPE_*,u_para + Maat_update_callback_t *update,//table line ,u_para + Maat_finish_callback_t *finish,//u_para + void* u_para); + +enum MAAT_SCAN_OPT +{ + MAAT_SET_SCAN_DISTRICT=1, //VALUE is a const char*,SIZE= strlen(string).DEFAULT: no default. + MAAT_SET_SCAN_LAST_REGION //VALUE is NULL, SIZE=0. This option indicates that the follow scan is the last region of current scan cobination. +}; +//return 0 if success, return -1 when failed; +int Maat_set_scan_status(Maat_feather_t feather,scan_status_t* mid,enum MAAT_SCAN_OPT type,const void* value,int size); + +//Return hit rule number, return -1 when error occurs,return -2 when hit current region +//mid MUST set NULL before fist call +int Maat_scan_intval(Maat_feather_t feather,int table_id + ,unsigned int intval + ,struct Maat_rule_t*result,int rule_num + ,scan_status_t *mid,int thread_num); +int Maat_scan_addr(Maat_feather_t feather,int table_id + ,struct ipaddr* addr + ,struct Maat_rule_t*result,int rule_num + ,scan_status_t *mid,int thread_num); +int Maat_scan_proto_addr(Maat_feather_t feather,int table_id + ,struct ipaddr* addr,unsigned short int proto + ,struct Maat_rule_t*result,int rule_num + ,scan_status_t *mid,int thread_num); +int Maat_full_scan_string(Maat_feather_t feather,int table_id + ,enum MAAT_CHARSET charset,const char* data,int data_len + ,struct Maat_rule_t*result,int* found_pos,int rule_num + ,scan_status_t* mid,int thread_num); +//hite_detail could be NULL if unconcern +int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id + ,enum MAAT_CHARSET charset,const char* data,int data_len + ,struct Maat_rule_t*result,int rule_num,struct Maat_hit_detail_t *hit_detail,int detail_num + ,int* detail_ret,scan_status_t* mid,int thread_num); + +stream_para_t Maat_stream_scan_string_start(Maat_feather_t feather,int table_id,int thread_num); +int Maat_stream_scan_string(stream_para_t* stream_para + ,enum MAAT_CHARSET charset,const char* data,int data_len + ,struct Maat_rule_t*result,int* found_pos,int rule_num + ,scan_status_t* mid); +//hited_detail could be NULL if unconcern +int Maat_stream_scan_string_detail(stream_para_t* stream_para + ,enum MAAT_CHARSET charset,const char* data,int data_len + ,struct Maat_rule_t*result,int rule_num,struct Maat_hit_detail_t *hit_detail,int detail_num + ,int* detail_ret,scan_status_t* mid); +void Maat_stream_scan_string_end(stream_para_t* stream_para); + +stream_para_t Maat_stream_scan_digest_start(Maat_feather_t feather,int table_id,unsigned long long total_len,int thread_num); +int Maat_stream_scan_digest(stream_para_t* stream_para + ,const char* data,int data_len,unsigned long long offset + ,struct Maat_rule_t*result,int rule_num + ,scan_status_t* mid); +void Maat_stream_scan_digest_end(stream_para_t* stream_para); + +int Maat_similar_scan_string(Maat_feather_t feather,int table_id + ,const char* data,int data_len + ,struct Maat_rule_t*result,int rule_num + ,scan_status_t* mid,int thread_num); + +void Maat_clean_status(scan_status_t* mid); + +#endif // H_MAAT_RULE_H_INCLUDE + diff --git a/support/include/field_stat2_for_view.h b/support/include/field_stat2_for_view.h new file mode 100644 index 0000000..7dbf5a5 --- /dev/null +++ b/support/include/field_stat2_for_view.h @@ -0,0 +1,66 @@ +#ifndef H_SCREEN_STAT2_H_INCLUDE +#define H_SCREEN_STAT2_H_INCLUDE +#include + +#ifndef __cplusplus +#error("This file should be compiled with C++ compiler") +#endif + +enum field_dsp_style_t +{ + FS_STYLE_FIELD=0, + FS_STYLE_COLUMN, + FS_STYLE_LINE, + FS_STYLE_STATUS +}; +enum field_calc_algo +{ + FS_CALC_CURRENT=0, + FS_CALC_SPEED +}; +enum field_op +{ + FS_OP_ADD=1, + FS_OP_SET +}; + + +typedef void* screen_stat_handle_t; + +enum FS_option +{ + OUTPUT_DEVICE, //VALUE is a const char*, indicate a file path string, SIZE = strlen(string+'\0')+1.DEFAULT:output to stdout. + PRINT_MODE, //VALUE is an interger,1:Rewrite ,2: Append. SIZE=4,DEFALUT:REWRITE. + STAT_CYCLE, //VALUE is an interger idicate interval seconds of every output, SIZE=4 ,DEFUALT:2 seconds. + PRINT_TRIGGER, //VALUE is an interger,1:Do print,0: Don't print.SIZE=4.DEFAULT:1. + CREATE_THREAD, //VALUE is an interger,1: Create a print thread,0:not create,output by call passive_output function, + //and the STAT_CYCLE is meaningless.SIZE=4,DEFAULT:0. + ID_INVISBLE, //value is field_id/status_id/column_id, not output this string, SIZE=4,DEFAULT: shutdown NO one. + FLUSH_BY_DATE, //value is 1(ture) or 0(false),SIZE=4,DEFAULT: Do not flush by date. + APP_NAME, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. DEFAULT is "?". + STATS_SERVER_IP, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. No DEFAULT. + STATS_SERVER_PORT, //VALUE is a unsigned short, host order, SIZE= sizeof(unsigned short). No DEFAULT. +}; + +//Always success. +screen_stat_handle_t FS_create_handle(void); + +int FS_set_para(screen_stat_handle_t handle, enum FS_option type,const void* value,int size); +void FS_start(screen_stat_handle_t handle); +void FS_stop(screen_stat_handle_t* handle); + +//return field_id/line_id/column_id greater than zero if success,return an interger less than zero if failed. +//should NOT include '\n','|' or ':' in the parameter name. +int FS_register(screen_stat_handle_t handle,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name); + +//numerator_id and denominator_id must be column/field/status style. +//scaling: negative value: zoom in; positive value: zoom out; +int FS_register_ratio(screen_stat_handle_t handle,int numerator_id,int denominator_id,int scaling,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name); + +//id: when id's type is FIELD , column_id is ignore. +int FS_operate(screen_stat_handle_t handle,int id,int column_id,enum field_op op,long long value); + +void FS_passive_output(screen_stat_handle_t handle); + +#endif + diff --git "a/support/include/\346\234\254\346\226\207\344\273\266\345\244\271\344\270\255\347\232\204\346\226\207\344\273\266\344\273\205\347\224\250\344\272\216\346\237\245\347\234\213_\344\270\215\347\274\226\350\257\221.txt" "b/support/include/\346\234\254\346\226\207\344\273\266\345\244\271\344\270\255\347\232\204\346\226\207\344\273\266\344\273\205\347\224\250\344\272\216\346\237\245\347\234\213_\344\270\215\347\274\226\350\257\221.txt" new file mode 100644 index 0000000..e69de29 diff --git a/support/ltsm/Makefile b/support/ltsm/Makefile new file mode 100644 index 0000000..1cb32b7 --- /dev/null +++ b/support/ltsm/Makefile @@ -0,0 +1,14 @@ +all:test_ltsm.so libltsm.a + +libltsm.a:ltsm.o + ar -r $@ $^; + cp $@ ../../lib + +test_ltsm.so:test_ltsm.o ltsm.o + gcc -fPIC -shared -o $@ $^ -I/opt/MESA/include/MESA + +test_ltsm.o:test_ltsm.c + gcc -fPIC -c -D__USE_MISC -D_BSD_SOURCE -o $@ $^ -I/opt/MESA/include/MESA + +ltsm.o:ltsm.c + gcc -fPIC -c -D__USE_MISC -D_BSD_SOURCE -o $@ $^ -I/opt/MESA/include/MESA diff --git a/support/ltsm/ltsm.c b/support/ltsm/ltsm.c new file mode 100644 index 0000000..c8af056 --- /dev/null +++ b/support/ltsm/ltsm.c @@ -0,0 +1,485 @@ + + +#include +#include +#include +#include + +/* + * The TCP state transition table needs a few words... + * + * We are the man in the middle. All the packets go through us + * but might get lost in transit to the destination. + * It is assumed that the destinations can't receive segments + * we haven't seen. + * + * The checked segment is in window, but our windows are *not* + * equivalent with the ones of the sender/receiver. We always + * try to guess the state of the current sender. + * + * The meaning of the states are: + * + * NONE: initial state + * SYN_SENT: SYN-only packet seen + * SYN_SENT2: SYN-only packet seen from reply dir, simultaneous open + * SYN_RECV: SYN-ACK packet seen + * ESTABLISHED: ACK packet seen + * FIN_WAIT: FIN packet seen + * CLOSE_WAIT: ACK seen (after FIN) + * LAST_ACK: FIN seen (after FIN) + * TIME_WAIT: last ACK seen + * CLOSE: closed connection (RST) + * + * Packets marked as IGNORED (sIG): + * if they may be either invalid or valid + * and the receiver may send back a connection + * closing RST or a SYN/ACK. + * + * Packets marked as INVALID (sIV): + * if we regard them as truly invalid packets + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ltsm.h" + + + +enum tcp_conntrack { + TCP_CONNTRACK_NONE, + TCP_CONNTRACK_SYN_SENT, + TCP_CONNTRACK_SYN_RECV, + TCP_CONNTRACK_ESTABLISHED, + TCP_CONNTRACK_FIN_WAIT, + TCP_CONNTRACK_CLOSE_WAIT, + TCP_CONNTRACK_LAST_ACK, + TCP_CONNTRACK_TIME_WAIT, + TCP_CONNTRACK_CLOSE, + TCP_CONNTRACK_LISTEN, /* obsolete */ +#define TCP_CONNTRACK_SYN_SENT2 TCP_CONNTRACK_LISTEN + TCP_CONNTRACK_MAX, + TCP_CONNTRACK_IGNORE +}; + + +/* What TCP flags are set from RST/SYN/FIN/ACK. */ +enum tcp_bit_set { + TCP_SYN_SET, + TCP_SYNACK_SET, + TCP_FIN_SET, + TCP_ACK_SET, + TCP_RST_SET, + TCP_NONE_SET, +}; + +#define TCP_URG_FLAG 0x20 +#define TCP_ACK_FLAG 0x10 +#define TCP_PSH_FLAG 0x08 +#define TCP_RST_FLAG 0x04 +#define TCP_SYN_FLAG 0x02 +#define TCP_FIN_FLAG 0x01 +#define TCP_FLAG_ALL 0x3F + + +#define sNO TCP_CONNTRACK_NONE +#define sSS TCP_CONNTRACK_SYN_SENT +#define sSR TCP_CONNTRACK_SYN_RECV +#define sES TCP_CONNTRACK_ESTABLISHED +#define sFW TCP_CONNTRACK_FIN_WAIT +#define sCW TCP_CONNTRACK_CLOSE_WAIT +#define sLA TCP_CONNTRACK_LAST_ACK +#define sTW TCP_CONNTRACK_TIME_WAIT +#define sCL TCP_CONNTRACK_CLOSE +#define sS2 TCP_CONNTRACK_SYN_SENT2 +#define sIV TCP_CONNTRACK_MAX +#define sIG TCP_CONNTRACK_IGNORE + +static const struct ltsm_result g_tsm_first_void = {FTSM_VOID, LTSM_VOID}; /* SYN, ״̬, void */ +static const struct ltsm_result g_tsm_first_start = {TCP_CONNTRACK_SYN_SENT, LTSM_START}; + + +static const char *g_ftsm_string[] = +{ + "VOID", + "FTSM_SYN_SENT", + "FTSM_SYN_RCVD", + "FTSM_ESTABLISHED", + "FTSM_FIN_WAIT", + "FTSM_CLOSE_WAIT", + "FTSM_LAST_ACK", + "FTSM_TIME_WAIT", + "FTSM_CLOSED", + "FTSM_LISTEN", + "__FTSM_MAX", +}; + +static const char *g_ltsm_string[] = +{ + "LTSM_VOID", + "LTSM_START", + "LTSM_DATA", + "LTSM_CLOSE", +}; + + + +static const enum light_tcp_state g_ltsm_full2light_table[12] = +{ + LTSM_VOID, /* TCP_CONNTRACK_NONE, */ + LTSM_START, /* TCP_CONNTRACK_SYN_SENT, */ + LTSM_DATA, /* TCP_CONNTRACK_SYN_RECV, */ + LTSM_DATA, /* TCP_CONNTRACK_ESTABLISHED, */ + LTSM_DATA, /* TCP_CONNTRACK_FIN_WAIT, */ + LTSM_DATA, /* TCP_CONNTRACK_CLOSE_WAIT, */ + LTSM_DATA, /* TCP_CONNTRACK_LAST_ACK, */ + LTSM_CLOSE, /* TCP_CONNTRACK_TIME_WAIT, */ + LTSM_CLOSE, /* TCP_CONNTRACK_CLOSE, */ + LTSM_VOID, /* TCP_CONNTRACK_LISTEN, */ + LTSM_VOID, /* TCP_CONNTRACK_MAX, */ + LTSM_VOID, /* TCP_CONNTRACK_IGNORE */ +}; + +/* + if dir == 0, packet from client; if dir == 1, packet from service. + + new_tcp_state = tcp_conntracks[dir][new_tcp_flag][old_tcp_state]; +*/ +static const uint8_t tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { + {/* ORIGINAL */ + /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 + */ + /*syn*/ {sSS, sSS, sIG, sIG, sIG, sIG, sIG, sSS, sSS, sS2}, + /* + * sNO -> sSS Initialize a new connection + * sSS -> sSS Retransmitted SYN + * sS2 -> sS2 Late retransmitted SYN + * sSR -> sIG + * sES -> sIG Error: SYNs in window outside the SYN_SENT state + * are errors. Receiver will reply with RST + * and close the connection. + * Or we are not in sync and hold a dead connection. + * sFW -> sIG + * sCW -> sIG + * sLA -> sIG + * sTW -> sSS Reopened connection (RFC 1122). + * sCL -> sSS + */ + /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 + */ + /*synack*/ {sIV, sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR}, + /* + * sNO -> sIV Too late and no reason to do anything + * sSS -> sIV Client can't send SYN and then SYN/ACK + * sS2 -> sSR SYN/ACK sent to SYN2 in simultaneous open + * sSR -> sIG + * sES -> sIG Error: SYNs in window outside the SYN_SENT state + * are errors. Receiver will reply with RST + * and close the connection. + * Or we are not in sync and hold a dead connection. + * sFW -> sIG + * sCW -> sIG + * sLA -> sIG + * sTW -> sIG + * sCL -> sIG + */ + /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 + */ + /*fin*/ {sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV}, + /* + * sNO -> sIV Too late and no reason to do anything... + * sSS -> sIV Client migth not send FIN in this state: + * we enforce waiting for a SYN/ACK reply first. + * sS2 -> sIV + * sSR -> sFW Close started. + * sES -> sFW + * sFW -> sLA FIN seen in both directions, waiting for + * the last ACK. + * Migth be a retransmitted FIN as well... + * sCW -> sLA + * sLA -> sLA Retransmitted FIN. Remain in the same state. + * sTW -> sTW + * sCL -> sCL + */ + /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 + */ + /*ack*/ {sES, sIV, sES, sES, sCW, sCW, sTW, sTW, sCL, sIV}, + /* + * sNO -> sES Assumed. + * sSS -> sIV ACK is invalid: we haven't seen a SYN/ACK yet. + * sS2 -> sIV + * sSR -> sES Established state is reached. + * sES -> sES :-) + * sFW -> sCW Normal close request answered by ACK. + * sCW -> sCW + * sLA -> sTW Last ACK detected. + * sTW -> sTW Retransmitted last ACK. Remain in the same state. + * sCL -> sCL + */ + /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 + */ + /*rst*/ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, + /*none*/ {sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV}}, + + {/******************************** REPLY *******************************/ + + /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 + */ + /*syn*/ {sIV, sS2, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sS2}, + /* + * sNO -> sIV Never reached. + * sSS -> sS2 Simultaneous open + * sS2 -> sS2 Retransmitted simultaneous SYN + * sSR -> sIV Invalid SYN packets sent by the server + * sES -> sIV + * sFW -> sIV + * sCW -> sIV + * sLA -> sIV + * sTW -> sIV Reopened connection, but server may not do it. + * sCL -> sIV + */ + /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 + */ + /*synack*/ {sIV, sSR, sSR, sIG, sIG, sIG, sIG, sIG, sIG, sSR}, + /* + * sSS -> sSR Standard open. + * sS2 -> sSR Simultaneous open + * sSR -> sSR Retransmitted SYN/ACK. + * sES -> sIG Late retransmitted SYN/ACK? + * sFW -> sIG Might be SYN/ACK answering ignored SYN + * sCW -> sIG + * sLA -> sIG + * sTW -> sIG + * sCL -> sIG + */ + /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 + */ + /*fin*/ {sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV}, + /* + * sSS -> sIV Server might not send FIN in this state. + * sS2 -> sIV + * sSR -> sFW Close started. + * sES -> sFW + * sFW -> sLA FIN seen in both directions. + * sCW -> sLA + * sLA -> sLA Retransmitted FIN. + * sTW -> sTW + * sCL -> sCL + */ + /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 + */ + /*ack*/ {sIV, sIG, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIG}, + /* + * sSS -> sIG Might be a half-open connection. + * sS2 -> sIG + * sSR -> sSR Might answer late resent SYN. + * sES -> sES :-) + * sFW -> sCW Normal close request answered by ACK. + * sCW -> sCW + * sLA -> sTW Last ACK detected. + * sTW -> sTW Retransmitted last ACK. + * sCL -> sCL + */ + /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 + */ + /*rst*/ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, + /*none*/ {sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV}} + }; + +typedef struct{ + uint32_t sip_net_order; + uint32_t dip_net_order; + uint16_t sport_net_order; + uint16_t dport_net_order; + uint8_t old_state; + uint8_t cur_state; + uint8_t create_dir; +}ltsm_inner_t; + + +const char *ltsm_fstate_ntop(enum full_tcp_state fstate) +{ + if((int)fstate < 0 || (int)fstate >= __FTSM_MAX){ + return "Invalid"; + } + + return g_ftsm_string[fstate]; +} + + +const char *ltsm_lstate_ntop(enum light_tcp_state lstate) +{ + if((int)lstate < 0 || (int)lstate > LTSM_CLOSE){ + return "Invalid"; + } + + return g_ltsm_string[lstate]; +} + + + +static inline uint32_t ltsm_get_tcpflags(const struct ltsm_tcphdr *th) { + if (th->th_flags & TCP_RST_FLAG) + return TCP_RST_SET; + else if (th->th_flags & TCP_SYN_FLAG) + return ((th->th_flags & TCP_ACK_FLAG) ? TCP_SYNACK_SET : TCP_SYN_SET); + else if (th->th_flags & TCP_FIN_FLAG) + return TCP_FIN_SET; + else if (th->th_flags & TCP_ACK_FLAG) + return TCP_ACK_SET; + else + return TCP_NONE_SET; +} + + +static inline uint32_t ltsm_convert_tcpflags(uint8_t th_flags) { + if (th_flags & TCP_RST_FLAG) + return TCP_RST_SET; + else if (th_flags & TCP_SYN_FLAG) + return ((th_flags & TCP_ACK_FLAG) ? TCP_SYNACK_SET : TCP_SYN_SET); + else if (th_flags & TCP_FIN_FLAG) + return TCP_FIN_SET; + else if (th_flags & TCP_ACK_FLAG) + return TCP_ACK_SET; + else + return TCP_NONE_SET; +} + + +ltsm_stream_handle ltsm_create_handle(void) +{ + ltsm_inner_t *ltsm_inner; + + ltsm_inner = calloc(1, sizeof(ltsm_inner_t)); + + ltsm_inner->old_state = TCP_CONNTRACK_SYN_SENT; + + return ltsm_inner; +} + + + +ltsm_stream_handle ltsm_create_stream_handle(const struct ltsm_iphdr * iphdr) +{ + const struct ltsm_tcphdr *tcp_hdr; + ltsm_inner_t *ltsm_inner; + int dir = 0; + uint32_t tcp_flags_set; + + if(IPPROTO_TCP != iphdr->ip_p){ + return NULL; + } + + tcp_hdr = (const struct ltsm_tcphdr *)((char *)iphdr + iphdr->ip_hl*4); + if(TH_SYN == tcp_hdr->th_flags){ + dir = 0; + }else if(TH_SYN|TH_ACK == tcp_hdr->th_flags){ + dir = 1; + }else{ + return NULL; + } + + ltsm_inner = calloc(1, sizeof(ltsm_inner_t)); + ltsm_inner->old_state = TCP_CONNTRACK_NONE; + ltsm_inner->sip_net_order = iphdr->ip_src.s_addr; + ltsm_inner->dip_net_order = iphdr->ip_dst.s_addr; + ltsm_inner->sport_net_order = tcp_hdr->th_sport; + ltsm_inner->dport_net_order = tcp_hdr->th_dport; + + tcp_flags_set = ltsm_get_tcpflags(tcp_hdr); + + ltsm_inner->cur_state = tcp_conntracks[dir][tcp_flags_set][ltsm_inner->old_state]; + ltsm_inner->create_dir = dir; + + return ltsm_inner; +} + + +uint8_t ltsm_proc_ipv4tcppkt(ltsm_stream_handle s_ltsm, const struct ltsm_iphdr *iphdr) +{ + uint8_t tcpstate; + ltsm_inner_t *ltsm_inner = (ltsm_inner_t *)s_ltsm; + int dir = 0; + uint32_t tcp_flags_set; + const struct ltsm_tcphdr *tcp_hdr; + + if(IPPROTO_TCP != iphdr->ip_p){ + return LTSM_VOID; + } + + tcp_hdr = (const struct ltsm_tcphdr *)((char *)iphdr + iphdr->ip_hl*4); + tcp_flags_set = ltsm_get_tcpflags(tcp_hdr); + + if((ltsm_inner->sip_net_order == iphdr->ip_src.s_addr) + && (ltsm_inner->dip_net_order == iphdr->ip_dst.s_addr) + && (ltsm_inner->sport_net_order == tcp_hdr->th_sport) + && (ltsm_inner->dport_net_order == tcp_hdr->th_dport)){ + dir = ltsm_inner->create_dir; + }else{ + dir = ltsm_inner->create_dir ^ 1; + } + + tcpstate = tcp_conntracks[dir][tcp_flags_set][ltsm_inner->old_state]; + + if(tcpstate < TCP_CONNTRACK_MAX){ + ltsm_inner->old_state = tcpstate; + } + + return tcpstate; +} + +void ltsm_destroy_stream_handle(ltsm_stream_handle pltsm) +{ + free(pltsm); +} + +void ltsm_destroy_handle(ltsm_stream_handle pltsm) +{ + free(pltsm); +} + + + +struct ltsm_result ltsm_get_current_state(ltsm_stream_handle pltsm, uint8_t tcp_flags, uint8_t dir) +{ + uint8_t tcp_fstate; + uint32_t tcp_flags_set; + struct ltsm_result res; + + if(NULL == pltsm){ + if(TH_SYN != tcp_flags){ + return g_tsm_first_void; + } + + return g_tsm_first_start; + } + + ltsm_inner_t *ltsm_inner = (ltsm_inner_t *)pltsm; + + tcp_flags_set = ltsm_convert_tcpflags(tcp_flags); + tcp_fstate = tcp_conntracks[dir][tcp_flags_set][ltsm_inner->old_state]; + + ltsm_inner->old_state = tcp_fstate; + + res.fstate = tcp_fstate; + res.lstate = g_ltsm_full2light_table[tcp_fstate]; + + return res; +} + + +uint32_t ltsm_tcp_key_generate(uint32_t sip_net_order, uint32_t dip_net_order, uint16_t sport_net_order, uint16_t dport_net_order) +{ + +} + +int ltsm_tcp_key_verify(const struct ip * iphdr) +{ + +} + diff --git a/support/ltsm/ltsm.h b/support/ltsm/ltsm.h new file mode 100644 index 0000000..340aa2f --- /dev/null +++ b/support/ltsm/ltsm.h @@ -0,0 +1,117 @@ +#ifndef __LTSM_H_ +#define __LTSM_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + LTSM : Light TCP State Machine. + Version : 2018-01-16 +*/ + +/* RFC׼TCPЭջ״̬ */ +enum full_tcp_state{ + FTSM_VOID, /* һĵһSYN, شֵ */ + FTSM_SYN_SENT, + FTSM_SYN_RCVD, + FTSM_ESTABLISHED, + FTSM_FIN_WAIT, + FTSM_CLOSE_WAIT, + FTSM_LAST_ACK, + FTSM_TIME_WAIT, + FTSM_CLOSED, + FTSM_LISTEN, + __FTSM_MAX, +}; + +/* + TCP״̬, + ʵֻ״̬:½, , , + ÿض1START1CLOSE״̬, ܰ0ɸDATA״̬. + + VOID״̬ڵ߿жǷҪ. +*/ +enum light_tcp_state{ + LTSM_VOID, /* һĵһSYN, شֵ */ + LTSM_START, + LTSM_DATA, + LTSM_CLOSE, +}; + +struct ltsm_iphdr + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ip_hl:4; /* header length */ + unsigned int ip_v:4; /* version */ +#endif +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int ip_v:4; /* version */ + unsigned int ip_hl:4; /* header length */ +#endif + u_int8_t ip_tos; /* type of service */ + u_short ip_len; /* total length */ + u_short ip_id; /* identification */ + u_short ip_off; /* fragment offset field */ +#define IP_RF 0x8000 /* reserved fragment flag */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u_int8_t ip_ttl; /* time to live */ + u_int8_t ip_p; /* protocol */ + u_short ip_sum; /* checksum */ + struct in_addr ip_src, ip_dst; /* source and dest address */ + }; + +struct ltsm_tcphdr + { + u_int16_t th_sport; /* source port */ + u_int16_t th_dport; /* destination port */ + u_int32_t th_seq; /* sequence number */ + u_int32_t th_ack; /* acknowledgement number */ +# if __BYTE_ORDER == __LITTLE_ENDIAN + u_int8_t th_x2:4; /* (unused) */ + u_int8_t th_off:4; /* data offset */ +# endif +# if __BYTE_ORDER == __BIG_ENDIAN + u_int8_t th_off:4; /* data offset */ + u_int8_t th_x2:4; /* (unused) */ +# endif + u_int8_t th_flags; +# define TH_FIN 0x01 +# define TH_SYN 0x02 +# define TH_RST 0x04 +# define TH_PUSH 0x08 +# define TH_ACK 0x10 +# define TH_URG 0x20 + u_int16_t th_win; /* window */ + u_int16_t th_sum; /* checksum */ + u_int16_t th_urp; /* urgent pointer */ +}; + +struct ltsm_result{ + enum full_tcp_state fstate; + enum light_tcp_state lstate; +}; + +typedef void * ltsm_stream_handle; + +ltsm_stream_handle ltsm_create_handle(void); + +#define LTSM_DIR_C2S 0 +#define LTSM_DIR_S2C 1 + +struct ltsm_result ltsm_get_current_state(ltsm_stream_handle pltsm, uint8_t tcp_flags, uint8_t dir); + +const char *ltsm_fstate_ntop(enum full_tcp_state fstate); +const char *ltsm_lstate_ntop(enum light_tcp_state lstate); + +void ltsm_destroy_handle(ltsm_stream_handle pltsm); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/support/ltsm/ltsm_with_hash.h b/support/ltsm/ltsm_with_hash.h new file mode 100644 index 0000000..0404f3d --- /dev/null +++ b/support/ltsm/ltsm_with_hash.h @@ -0,0 +1,81 @@ +#ifndef LTSM_H_ +#define LTSM_H_ + +#include +#include +#include +#include "mesa_net.h" +/* + LTSM : Light TCP State Machine. + +*/ + +/* RFC׼TCPЭջ״̬ */ +enum full_tcp_state{ + FTSM_CLOSED, + FTSM_LISTEN, + FTSM_SYN_SENT, + FTSM_SYN_RCVD, + FTSM_ESTABLISHED, + FTSM_CLOSE_WAIT, + FTSM_LAST_ACK, + FTSM_FIN_WAIT1, + FTSM_FIN_WAIT2, + FTSM_CLOSING, + FTSM_TIME_WAIT, +}; + +/* + TCP״̬, + ֻ״̬:½, , , + ÿض1START1CLOSE״̬, ܰ0ɸDATA״̬. +*/ +enum light_tcp_state{ + LTSM_START, + LTSM_DATA, + LTSM_CLOSE, + LTSM_INVALID, +}; + + +enum light_tsm_opt{ + LTSMO_THREAD_NUM, /* ߳, ѡ:uint32 */ + LTSMO_CREATE_MODE, /* ģʽ, 1:SYN; 2:ݰɴ, ѡ:uint32 */ + LTSMO_MAX_STREAM_NUM, /* TCP󲢷, forÿ߳, ѡ:uint32 */ + LTSMO_STREAM_TIMEOUT, /* ʱ̭ʱ, λ:, 0ʾʱ. ѡ:uint32 */ +}; + +struct ltsm_result{ + enum full_tcp_state fstate; + enum light_tcp_state lstate; + void *pme; +}; + +typedef void * ltsm_global_handle; +typedef void * ltsm_stream_handle; + +/* ltsmȫ־ʼ */ +void *ltsm_init(void); + +/* ltsmز */ +int ltsm_set_opt(ltsm_global_handle pltsm, enum light_tsm_opt opt, void *value, int value_len); + +/* ltsm */ +int ltsm_run(ltsm_global_handle pltsm); + +/* IPv4, صǰltsm״̬, pmeⲿߴ洢Զ, ڴͷ */ +struct ltsm_result *ltsm_proc_ip4pkt(ltsm_global_handle pltsm, int tseq, const struct ip *ip4hdr); + +/* IPv4ͷ+TCPͷ, صǰltsm״̬, pmeⲿߴ洢Զ, ڴͷ */ +struct ltsm_result *ltsm_proc_ip4tcppkt(ltsm_global_handle pltsm, int tseq, const struct ip *ip4hdr, const struct tcphdr *tcp_hdr); + +/* IPv6, صǰltsm״̬, pmeⲿߴ洢Զ, ڴͷ */ +struct ltsm_result *ltsm_proc_ip6pkt(ltsm_global_handle pltsm, int tseq, const struct ip6_hdr *ip6hdr); + +/* IPv6ͷ+TCPͷ, صǰltsm״̬, pmeⲿߴ洢Զ, ڴͷ */ +struct ltsm_result *ltsm_proc_ip6tcppkt(ltsm_global_handle pltsm, int tseq, const struct ip6_hdr *ip6hdr, const struct tcphdr *tcp_hdr); + +uint8_t ltsm_proc_ipv4tcppkt(ltsm_stream_handle s_ltsm, const struct mesa_ip4_hdr *iphdr); + +void ltsm_destroy_stream_handle(ltsm_stream_handle s_ltsm); +#endif \ No newline at end of file diff --git a/support/ltsm/test_ltsm.c b/support/ltsm/test_ltsm.c new file mode 100644 index 0000000..01935a9 --- /dev/null +++ b/support/ltsm/test_ltsm.c @@ -0,0 +1,59 @@ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stream.h" +#include "ltsm.h" + + + + +char LTSM_TCPALL_ENTRY(struct streaminfo *pstream, void **pme, int thread_seq,void *apacket) +{ + void *ltsm_handle; + struct ltsm_result tcpstate; + const struct ltsm_tcphdr *tcp_hdr; + const struct ip *iphdr = (const struct ip *)apacket; + + if(apacket != NULL){ + tcp_hdr = (const struct ltsm_tcphdr *)((char *)iphdr + iphdr->ip_hl*4); + } + + if(OP_STATE_PENDING == pstream->pktstate){ + tcpstate = ltsm_get_current_state(NULL, tcp_hdr->th_flags, pstream->curdir); + if(LTSM_START == tcpstate.lstate ){ + ltsm_handle = ltsm_create_handle(); + *pme = ltsm_handle; + }else{ + return APP_STATE_DROPME; + } + }else{ + ltsm_handle = *pme; + if(OP_STATE_CLOSE == pstream->pktstate){ + ltsm_destroy_handle(ltsm_handle); + return APP_STATE_DROPME; + } + } + + + tcpstate = ltsm_get_current_state(ltsm_handle, tcp_hdr->th_flags, pstream->curdir - 1); + + printf("stream: %s, flags:0x%x, fstate: %s,\t lstate:%s\n", printaddr(&pstream->addr, thread_seq), tcp_hdr->th_flags, ltsm_fstate_ntop(tcpstate.fstate), ltsm_lstate_ntop(tcpstate.lstate)); + + return APP_STATE_GIVEME; +} + + +int LTSM_INIT(void) +{ + return 1; +} + + + diff --git a/test/mutex_vs_rdlock.c b/test/mutex_vs_rdlock.c new file mode 100644 index 0000000..e05ee65 --- /dev/null +++ b/test/mutex_vs_rdlock.c @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#define LOCK_TYPE (2) /* 1:mutex; 2:rwlock; 3:atomic */ + +#if LOCK_TYPE==1 +pthread_rwlock_t test_rwlock; +#elif LOCK_TYPE==2 +pthread_mutex_t test_mlock; +#elif LOCK_TYPE==3 +long atomic_lock = 0; +#endif + +unsigned long long g_val; + +unsigned long long g_producer_op_times = 0, g_customer_op_times; + + +static inline void test_lock(long lock_val) +{ +#if LOCK_TYPE==1 + pthread_rwlock_wrlock(&test_rwlock); +#elif LOCK_TYPE==2 + pthread_mutex_lock(&test_mlock); +#elif LOCK_TYPE==3 + while((__sync_or_and_fetch(&atomic_lock, lock_val) & 0xF) == lock_val){ + ; + } +#endif + +} + +static inline void test_rlock(long lock_val) +{ +#if LOCK_TYPE==1 + pthread_rwlock_rdlock(&test_rwlock); +#elif LOCK_TYPE==2 + pthread_mutex_lock(&test_mlock); +#elif LOCK_TYPE==3 + while((__sync_or_and_fetch(&atomic_lock, lock_val) & 0xF) == lock_val){ + ; + } +#endif + +} + +static inline void test_unlock(long lock_mask) +{ +#if LOCK_TYPE==1 + pthread_rwlock_unlock(&test_rwlock); +#elif LOCK_TYPE==2 + pthread_mutex_unlock(&test_mlock); +#elif LOCK_TYPE==3 + __sync_and_and_fetch(&atomic_lock, lock_mask); +#endif +} + +/* + bit: producer; + 2bit : customer; +*/ + +static void *producer_thread(void *arg) +{ + int i; + + //for(i = 0; i < 9999999; i++){ + while(1){ + test_lock(0x01); + g_val++; + test_unlock(0xFE); + g_producer_op_times++; + } + + return NULL; +} + +static void *customer_thread(void *arg) +{ + unsigned long long tmp; + int i; + + //for(i = 0; i < 9999999; i++){ + while(1){ + test_rlock(0x02); + tmp = g_val; + test_unlock(0xFD); + g_customer_op_times++; + } + + return NULL; +} + +static void *stat_thread(void *arg) +{ + unsigned long long last_op_times = 0; + + while(1){ + printf("op PPS: %llu\n", g_customer_op_times + g_producer_op_times - last_op_times); + last_op_times = g_customer_op_times + g_producer_op_times; + sleep(1); + } + + return NULL; +} + +int main(void) +{ +#if LOCK_TYPE==1 + pthread_rwlock_init(&test_rwlock, NULL); +#elif LOCK_TYPE==2 + pthread_mutex_init(&test_mlock, NULL); +#endif + + pthread_t stat_pid, producer_pid, customer_pid; + + pthread_create(&stat_pid, NULL, stat_thread, NULL); + + pthread_create(&producer_pid, NULL, producer_thread, NULL); + pthread_create(&customer_pid, NULL, customer_thread, NULL); + + pthread_join(producer_pid, NULL); + pthread_join(customer_pid, NULL); + + printf("%llu\n", g_val); + + return 0; +} + diff --git a/test/sport_usable.c b/test/sport_usable.c new file mode 100644 index 0000000..1f9ec6b --- /dev/null +++ b/test/sport_usable.c @@ -0,0 +1,45 @@ +#include + +#define TOT_ACC_GW_NUM (10) +#define THIS_ACC_GW_ID (5) +#define THREAD_NUM (8) + +/* for test */ +static int flwd_act_ip_get_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 = + 64511 / TOT_ACC_GW_NUM; + + this_gateway_begin_port = + this_gateway_usable_tot_count * (THIS_ACC_GW_ID-1) + 1025; + + this_thread_usable_tot_count = + this_gateway_usable_tot_count / THREAD_NUM; + + *usable_count = + this_gateway_usable_tot_count / THREAD_NUM; + + *begin_port = this_gateway_begin_port + (*usable_count) * tid; + + return 0; +} + +int main(void) +{ + int i; + unsigned short begin_port; + unsigned short usable_count; + + for(i =0; i < THREAD_NUM; i++){ + flwd_act_ip_get_usable_sport(i, &begin_port, &usable_count); + printf("thread:%d, begin:%u, count:%u\n", i, begin_port, usable_count); + } + return 0; +} + + -- cgit v1.2.3