diff options
| author | lijia <[email protected]> | 2018-10-24 09:36:45 +0800 |
|---|---|---|
| committer | lijia <[email protected]> | 2018-10-24 09:36:45 +0800 |
| commit | 86a43b4d325ddc850fa9dc4711670880f35b11e8 (patch) | |
| tree | 8356a056ac9bfb8cf14fcf57f113dd306b4277d1 /src/packet_io | |
create new project.
Diffstat (limited to 'src/packet_io')
| -rw-r--r-- | src/packet_io/Makefile | 34 | ||||
| -rw-r--r-- | src/packet_io/flwd_io_pcap.so | bin | 0 -> 30411 bytes | |||
| -rw-r--r-- | src/packet_io/flwd_io_socket.so | bin | 0 -> 26649 bytes | |||
| -rw-r--r-- | src/packet_io/flwd_packet_io.c | 193 | ||||
| -rw-r--r-- | src/packet_io/flwd_packet_io_pcap.c | 428 | ||||
| -rw-r--r-- | src/packet_io/flwd_packet_io_socket.c | 376 | ||||
| -rw-r--r-- | src/packet_io/nf-queue.c | 213 | ||||
| -rw-r--r-- | src/packet_io/nfq_test.c | 270 |
8 files changed, 1514 insertions, 0 deletions
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 Binary files differnew file mode 100644 index 0000000..7af3822 --- /dev/null +++ b/src/packet_io/flwd_io_pcap.so diff --git a/src/packet_io/flwd_io_socket.so b/src/packet_io/flwd_io_socket.so Binary files differnew file mode 100644 index 0000000..7db273b --- /dev/null +++ b/src/packet_io/flwd_io_socket.so 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 <linux/limits.h> +#include <stdio.h> +#include <dlfcn.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> + + +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()�Ⱥ���, ������Ҫ��̬�����հ��߳�, + ������marsio��IO��, �������հ���ѯģʽ, 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 <pcap/pcap.h> +#include "MESA_list_queue.h" +#include "MESA_handle_logger.h" +#include "MESA_prof_load.h" +#include <sys/types.h> +#include <sys/socket.h> +#include <string.h> +#include <arpa/inet.h> +#include <assert.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <net/if_arp.h> +#include <net/if.h> + +#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 <pcap/pcap.h> +#include "MESA_list_queue.h" +#include "MESA_handle_logger.h" +#include "MESA_prof_load.h" +#include <sys/types.h> +#include <sys/socket.h> +#include <string.h> +#include <arpa/inet.h> +#include <assert.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <net/if_arp.h> +#include <net/if.h> +#include <stdlib.h> + +#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, �����vxlan����MACͷ+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, ����vxlan����MACͷ+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��ʼ��ԭʼ��, ģ��vxlan���ethernet */ + ehdr = (flwd_eth_hdr_t *)(sock_mbuff->data_actual_ptr); + ehdr->h_proto = htons(ETH_P_IP); + + /* ģ��vxlan���ipv4 */ + 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <time.h> +#include <arpa/inet.h> + +#include <libmnl/libmnl.h> +#include <linux/netfilter.h> +#include <linux/netfilter/nfnetlink.h> + +#include <linux/types.h> +#include <linux/netfilter/nfnetlink_queue.h> + +#include <libnetfilter_queue/libnetfilter_queue.h> + +/* only for NFQA_CT, not needed otherwise: */ +#include <linux/netfilter/nfnetlink_conntrack.h> + +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), [email protected]
+ * Company: HIT
+ *
+ * =====================================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <asm/byteorder.h>
+#include <linux/netfilter.h>
+#include <libnetfilter_queue/libnetfilter_queue.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+#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);
+}
|
