commit c9c3fe7fbdc9f12648ae16a9ea50e886509c7238 Author: linuxrc@163.com Date: Tue Nov 30 12:55:56 2021 +0800 创建 diff --git a/bin/conf/project_list.conf b/bin/conf/project_list.conf new file mode 100644 index 0000000..34829f0 --- /dev/null +++ b/bin/conf/project_list.conf @@ -0,0 +1,23 @@ +#project_requirement_name value_type +#current requirement definitions: +# terminal_tag, +# ipv4_frag_list, +# ipv6_frag_list, +# stream_id, +# value type definitions +# char, +# short, +# int, +# long, +# struct + +#terminal_tag struct +#ipv4_frag_list struct +#ipv6_frag_list struct +#stream_id struct +#test_project struct +#tcp_flow_stat struct +#udp_flow_stat struct + +JT_IP_PKT struct +STREAMID long diff --git a/bin/conf/qq_file_trans.conf b/bin/conf/qq_file_trans.conf new file mode 100644 index 0000000..d10ec29 --- /dev/null +++ b/bin/conf/qq_file_trans.conf @@ -0,0 +1,33 @@ +[MODULE] +#日志 +RUN_LOG_DIR=./log/qq_file_trans/ +RUN_LOG_LEVEL=40 + +#存本地文件开关 +DEBUG_SWITCH=0 + +#统计信息 +STAT_FIELD_CYCLE=300 +STAT_FIELD_TRIG=0 + + +[FEATURE] +#FEATURE_QQ_NUMBER_TCP=0:27,00,00,00,00,14;0:04,37,21 +#FEATURE_QQ_TCPFILENAME=0:0c,00,00,00,00,2b;31:0c,00,00,00,00,2b +#FEATURE_QQ_TCPFILE=0:04,36,43,00&39:65,65,00,00 + +FEATURE_QQ_NUMBER_TCP=0:04&13:00,01,00,00,00,00,00 +FEATURE_QQ_TCPFILENAME=0:04&13:00,01,00,00,00,00,00&31:0c,00,00,00,00,2b +FEATURE_QQ_TCPFILE=0:04&13:00,01,00,00,00,00,00&39:65,65,00,00 +FEATURE_QQ_TCPFILE_END=0:04&13:00,01,00,00,00,00,00&39:56,56,00,00 + +#文件应该也有特征13:00,01,00,00,00,00,00 +FEATURE_QQ_NUMBER_UDP=0:03,00,01,00,00,00,00,00;13:00,01,00,00,00,00,00 +FEATURE_QQ_UDPFILENAME=3:00,2b,52,00,00;34:00,2b,52,00,00 +FEATURE_QQ_UDPFILE_START=3:00,2d,63,00;34:00,2d,63,00 +FEATURE_QQ_UDPFILE_END=3:00,2b,56,00,00;34:00,2b,56,00,00 + +#其他QQ协议特征,上面的也会作为协议特征 +FEATURE_QQTCP_PROTOCOL= +FEATURE_QQUDP_PROTOCOL= + diff --git a/bin/plug/business/conflist_business.inf b/bin/plug/business/conflist_business.inf new file mode 100644 index 0000000..f5ca2a2 --- /dev/null +++ b/bin/plug/business/conflist_business.inf @@ -0,0 +1,24 @@ +##./plug/business/test_app/test_app.inf +##./plug/business/test_http/test_http.inf +##./plug/business/ipsec_biz_sample/ipsec_biz_sample.inf +##./plug/business/l2tp_biz_sample/l2tp_biz_sample.inf +##./plug/business/pptp_biz_sample/pptp_biz_sample.inf +##./plug/business/terminal_tag/terminal_tag.inf +##./plug/business/g_device_plug/g_device_plug.inf +# +#./plug/business/ycl_ftp/ycl_ftp.inf +#./plug/business/ycl_mail/ycl_mail.inf +#./plug/business/ycl_http_service/ycl_http_service.inf +##./plug/business/ycl_http_netdisk/ycl_http_netdisk.inf +#./plug/business/ycl_http_webmail/ycl_http_webmail.inf +##./plug/business/ycl_qq_biz/ycl_qq_biz.inf +##./plug/business/ycl_qq/ycl_qq_biz.inf +# +#./plug/business/http_jt_audit/http_jt_audit.inf +#./plug/business/dns_audit/dns_jt_audit.inf +#./plug/business/mail_audit/mail_jt_audit.inf +#./plug/business/ssl_audit/ssl_audit.inf +#./plug/business/ftp_audit/ftp_audit.inf +#./plug/business/ip_jt/ip_jt.inf +##./plug/business/MESA_capfile/MESA_capfile.inf +./plug/business/qq_file_trans/qq_file_trans.inf diff --git a/bin/plug/business/qq_file_trans/qq_file_trans.inf b/bin/plug/business/qq_file_trans/qq_file_trans.inf new file mode 100644 index 0000000..14f1d5e --- /dev/null +++ b/bin/plug/business/qq_file_trans/qq_file_trans.inf @@ -0,0 +1,13 @@ +[PLUGINFO] +PLUGNAME=QQ_FILE_TRANS +SO_PATH=./plug/business/qq_file_trans/qq_file_trans.so +INIT_FUNC=QQ_PROT_INIT +DESTROY_FUNC=QQ_PROT_DESTROY + +[UDP] +FUNC_FLAG=ALL +FUNC_NAME=QQ_PROT_UDP_ENTRY + +[TCP] +FUNC_FLAG=ALL +FUNC_NAME=QQ_PROT_TCP_ENTRY diff --git a/bin/plug/business/qq_file_trans/qq_file_trans.so b/bin/plug/business/qq_file_trans/qq_file_trans.so new file mode 100644 index 0000000..f5b315c Binary files /dev/null and b/bin/plug/business/qq_file_trans/qq_file_trans.so differ diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..ee38172 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,21 @@ +CC=g++ +CCC=g++ + +INC_PATH = -I./include +CFLAGS = -Wall -g -fPIC $(INC_PATH) + +LIBS = -lMESA_prof_load -lMESA_handle_logger -ldocumentanalyze -lMESA_field_stat -lpthread + +OBJS = qq_file_global.o qq_file_entry.o + +TARGET = qq_file_trans.so + +$(TARGET):$(OBJS) + $(CCC) -fPIC -shared $^ -o $@ $(LIBS) + cp $@ /home/zhangcw/sapp/plug/business/qq_file_trans/ + +.c.o: + $(CC) -c $(CFLAGS) $< + +clean: + rm -f $(TARGET) $(OBJS) diff --git a/src/include/connector.h b/src/include/connector.h new file mode 100644 index 0000000..b1c10f1 --- /dev/null +++ b/src/include/connector.h @@ -0,0 +1,86 @@ +#ifndef CONNECTOR_H_ +#define CONNECTOR_H_ + +extern int CONNECTOR_VERSION_1_20170704; + +typedef unsigned long ulong64; +typedef unsigned int uint32; + +typedef enum +{ + APPD_SENDBACK=0, //ǰӦòݻش + APPD_FILE=1, //ļģӦòݷַ +}APPD_HEADER_TYPE; + +typedef enum +{ + DEST_APPD=0, //ݷַappd + DEST_WM=1, //webmailWM + DEST_MLFA=2, //ļmlfa +}APPD_DESTINATION; + +typedef enum +{ + COMPLETE=0, + FRAG=1, + FRAG_END=2, +}APPD_MSG_TYPE; + +typedef struct _appd_basic_t +{ + APPD_HEADER_TYPE appd_type; //Ӧòݻļ + const char* service_name; //,'\0' + APPD_DESTINATION destination; //ݽճ + ulong64* streamid; //ָ̬룬id + uint32 streamid_num; + struct ipaddr* addr; //ָ̬룬 Ԫ + uint32 addr_num; +}appd_basic_t; + + +#ifdef __cplusplus +extern "C" { +#endif + +/*ʼconnector ÿһһ*/ +//void* connector_start(appd_basic_t* baisc_info); +void* connector_start(appd_basic_t* baisc_info, const struct streaminfo *a_tcp); +/* msg_type: COMPLETE FRAG FRAG_END*/ +void connector(void* handler, APPD_MSG_TYPE msg_type, void* simple_opt_handle, void* nested_opt_handle); +/*ÿһ*/ +void connector_finish(void* handler); + + +/*ѡ*/ +/*1. üѡĸsimple_opt_handle*/ +void* connector_create_simple_opt(uint32 max_size); +/*2. ѡ*/ +int connector_append_simple_opt(void* simple_opt_handle, const char* opt_name, char* opt_value, uint32 opt_len); +/*3. ͷ*/ +void connector_free_simple_opt(void** simple_opt_handle); + + +/*Ƕѡ*/ +/*1. Ƕѡܸnested_opt_handle*/ +void* connector_create_nested_opt(uint32 max_size); +/*2. ijǶѡԼڲѡĸnested_unit_handle*/ +void* connector_create_nested_opt_unit(const char* nested_unit_name, uint32 max_size); +/*3.䵥Ƕѡڲѡ*/ +/*opt_unit_handle connector_create_nested_opt_unitķֵ*/ +/*ֵ 0 OK -1 ERROR*/ +int connector_append_nested_opt_unit(void* nested_unit_handle, const char* subopt_name, char* subopt_value, uint32 subopt_len); +/*4. Ƕѡ׷Ƕѡnested_opt_handle*/ +/*ֵ 0 OK -1 ERROR*/ +int connector_append_nested_opt(void* nested_opt_handle, void* nested_unit_handle); +/*5. ͷŵǶѡ*/ +void connector_free_nested_opt_unit(void** nested_unit_handle); +/*6. ͷ*/ +void connector_free_nested_opt(void** nested_opt_handle); + + +#ifdef __cplusplus +} +#endif +#endif + + diff --git a/src/qq_file_entry.c b/src/qq_file_entry.c new file mode 100644 index 0000000..ad49b50 --- /dev/null +++ b/src/qq_file_entry.c @@ -0,0 +1,868 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "qq_file_entry.h" +#include "qq_file_global.h" +#include "connector.h" + +qq_global_info_t g_qq_global_info; + +int data_hit_feature(const char *data, unsigned int datalen, unsigned int min_len, FEATURE_INDEX_T index) +{ + unsigned int i, j; + + if(datalen > min_len) + { + for(i=0; ithread_id = thread_id; + qq_pme->qq_state = QQ_STATE_INIT; + qq_pme->pending_flag = 1; + qq_pme->fileinfo.block_seq = -1; //UDPʼ-1ʶش + qq_pme->tcp_flag = tcp_flag; + + *pme = qq_pme; + + if(g_qq_global_info.stat_trig) + { + stat_field_operation(g_qq_global_info.stat_handle, g_qq_global_info.stat_id[STAT_ID_SESSION_NUM], FS_OP_TYPE_ADD, 1); + stat_field_operation(g_qq_global_info.stat_handle, g_qq_global_info.stat_id[STAT_ID_NEW_SESSION], FS_OP_TYPE_ADD, 1); + } + + return 0; +} + +static void clear_qq_pme_info(qq_proto_pme_t *qq_pme, struct streaminfo *a_udp, const void *raw_pkt) +{ + if(qq_pme->connector_hdl != NULL) + { + connector_finish(qq_pme->connector_hdl); + } + if(qq_pme->fileinfo.buf) + { + dictator_free(qq_pme->thread_id, qq_pme->fileinfo.buf); + } + + dictator_free(qq_pme->thread_id, qq_pme); + + if(g_qq_global_info.stat_trig) + { + stat_field_operation(g_qq_global_info.stat_handle, g_qq_global_info.stat_id[STAT_ID_SESSION_NUM], FS_OP_TYPE_ADD, -1); + stat_field_operation(g_qq_global_info.stat_handle, g_qq_global_info.stat_id[STAT_ID_DEL_SESSION], FS_OP_TYPE_ADD, 1); + } +} + +QQ_STATE_t analyse_udp_pdata_state(QQ_STATE_t state, const char *data, int datalen) +{ + if(state != QQ_STATE_INIT) + return state; + + return assign_qq_state(is_qq_protocol_udp(data, datalen)); +} + +QQ_STATE_t analyse_tcp_pdata_state(QQ_STATE_t state, const char *data, int datalen) +{ + if(state != QQ_STATE_INIT) + return state; + + return assign_qq_state(is_qq_protocol_tcp(data, datalen)); +} + +int process_udp_data_state(struct streaminfo *a_udp, qq_proto_pme_t *qq_pme, int thread_seq,const void *raw_pkt) +{ + char *data = (char *)a_udp->pudpdetail->pdata; + int datalen = a_udp->pudpdetail->datalen; + char filename[512]; + int tmp, i, j; + + switch(qq_pme->qq_state) + { + case QQ_STATE_QQNUM: + qq_pme->qq_state = QQ_STATE_INIT; + if(qq_pme->qqnum[a_udp->curdir-1] || qq_pme->qqnum_from) + break; + + if(*data == 0x03 && datalen==27) + { + qq_pme->qqnum[a_udp->curdir-1] = ntohl(*((unsigned int *)&data[23])); + } + else if(*data == 0x04) //TODO + { + qq_pme->qqnum_from = ntohl(*((unsigned int *)&data[9])); + } + break; + + case QQ_STATE_FNAME: + qq_pme->qq_state = QQ_STATE_INIT; + qq_pme->file_dir = a_udp->curdir - 1; + + if(*data == 0x05 && datalen < 800) //800---д + { + qq_pme->total_file_len = ntohl(*((unsigned int *)&data[11])); + for (i = 23, j = 0; i < datalen - 1; i+=2, j+=2) + { + if ((data[i] == 0x00) && (data[i + 1] == 0x00)) + break; + filename[j] = data[i]; + filename[j+1] = data[i+1]; + } + tmp = j; + } + else if(*data == 0x04 && datalen < 800) + { + if(qq_pme->qqnum_from == 0) + { + qq_pme->qqnum_from = ntohl(*((unsigned int *)&data[9])); + } + qq_pme->total_file_len = ntohl(*((unsigned int *)&data[42])); + for (i = 54, j = 0; i < datalen - 1; i+=2, j+=2) + { + if ((data[i] == 0x00) && (data[i + 1] == 0x00)) + break; + filename[j] = data[i]; + filename[j+1] = data[i+1]; + } + tmp = j; + } + else + { + return APP_STATE_GIVEME; + } + return protocol_process(qq_pme, QQ_FILENAME, filename, tmp, a_udp, raw_pkt); + + case QQ_STATE_FCONT_START: + qq_pme->qq_state = QQ_STATE_INIT; //ÿǰ涼 + if(*data == 0x05 && datalen>18) + { + tmp = ntohl(*((int *)&data[10])); //TODO֪intͻshort + if(qq_pme->fileinfo.block_seq >= tmp) + return APP_STATE_GIVEME; + + qq_pme->fileinfo.block_seq = tmp; + qq_pme->compress_flag = data[17]; + return protocol_process(qq_pme, QQ_FILECONT, data+18, datalen-18, a_udp, raw_pkt); + } + else if(*data==0x04 && datalen>50) + { + tmp = ntohl(*((int *)&data[41])); //TODO֪intͻshort + if(qq_pme->fileinfo.block_seq >= tmp) + return APP_STATE_GIVEME; + + qq_pme->fileinfo.block_seq = tmp; + qq_pme->compress_flag = data[48]; + return protocol_process(qq_pme, QQ_FILECONT, data+49, datalen-50, a_udp, raw_pkt); + } + break; + + case QQ_STATE_FCONT_END: + qq_pme->qq_state = QQ_STATE_INIT; + if(*data == 0x05 && datalen>18) + { + qq_pme->compress_flag = data[17]; + return protocol_process(qq_pme, QQ_FILECONT_END, data+18, datalen-18, a_udp, raw_pkt); + } + else if(*data == 0x04 && datalen>50) + { + qq_pme->compress_flag = data[48]; + return protocol_process(qq_pme, QQ_FILECONT_END, data+49, datalen-50, a_udp, raw_pkt); + } + break; + + case QQ_STATE_FCONT: + case QQ_STATE_INIT: + default: + break; + } + + return APP_STATE_GIVEME; +} + +extern "C" char QQ_PROT_UDP_ENTRY(struct streaminfo *a_udp, void **pme, int thread_seq,const void *raw_pkt) +{ + QQ_PACKET_TYPE_t type; + qq_proto_pme_t *qq_pme=(qq_proto_pme_t*)(*pme); + int rec = APP_STATE_GIVEME; + + switch(a_udp->opstate) + { + case OP_STATE_PENDING: + type = is_qq_protocol_udp((char *)a_udp->pudpdetail->pdata, a_udp->pudpdetail->datalen); + if(type) + { + if(init_qq_pme_info(&qq_pme, a_udp->threadnum, 0)) + return APP_STATE_DROPME; + qq_pme->qq_state = assign_qq_state(type); + *pme = qq_pme; + } + else + { + return APP_STATE_DROPME; + } + //no break here + + case OP_STATE_DATA: + qq_pme->qq_state = analyse_udp_pdata_state(qq_pme->qq_state, (char *)a_udp->pudpdetail->pdata, a_udp->pudpdetail->datalen); + + rec = process_udp_data_state(a_udp, qq_pme, thread_seq, raw_pkt); + break; + + case OP_STATE_CLOSE: + clear_qq_pme_info(qq_pme, a_udp, raw_pkt); + break; + + default: + return APP_STATE_DROPME; + } + + if(rec & APP_STATE_DROPME) + { + clear_qq_pme_info(qq_pme, a_udp, raw_pkt); + } + + return rec; +} + + +int process_tcp_data_state(struct streaminfo *a_tcp, qq_proto_pme_t *qq_pme, int thread_seq,const void *raw_pkt) +{ + char *data = (char *)a_tcp->pudpdetail->pdata; + int datalen = a_tcp->pudpdetail->datalen; + char filename[512]; + int cur_len=0, i, j, rec = APP_STATE_GIVEME, need_len; + + switch(qq_pme->qq_state) + { + case QQ_STATE_QQNUM: + qq_pme->qq_state = QQ_STATE_INIT; + if(qq_pme->qqnum_from) + break; + + if(*data == 0x04) //TODO + { + qq_pme->qqnum_from = ntohl(*((unsigned int *)&data[9])); + } + break; + + case QQ_STATE_FNAME: + qq_pme->qq_state = QQ_STATE_INIT; + qq_pme->file_dir = a_tcp->curdir - 1; + + //ȡļļUNICODE + if(*data == TCPFILE_START_CHAR0c && datalen < 800) //800---д + { + qq_pme->total_file_len = ntohl(*((unsigned int *)&data[27])); + for (i = 39, j = 0; i < datalen - 1; i+=2, j+=2) + { + if ((data[i] == 0x00) && (data[i + 1] == 0x00)) + break; + filename[j] = data[i]; + filename[j+1] = data[i+1]; + } + cur_len = j; + } + else if(*data == TCPFILE_START_CHAR04 && datalen < 800) + { + qq_pme->total_file_len = ntohl(*((unsigned int *)&data[90])); + for (i = 102, j = 0; i < datalen - 1; i+=2, j+=2) + { + if ((data[i] == 0x00) && (data[i + 1] == 0x00)) + break; + filename[j] = data[i]; + filename[j+1] = data[i+1]; + } + cur_len = j; + } + else + { + return APP_STATE_GIVEME; + } + return protocol_process(qq_pme, QQ_FILENAME, filename, cur_len, a_tcp, raw_pkt); + + case QQ_STATE_FCONT_START: + //UDPͬǣTCPͷһǰƥʽ䣻 + if(a_tcp->curdir != qq_pme->file_dir+1) + break; + + if(a_tcp->ptcpdetail->lostlen) //ѰҰͷ + { + qq_pme->fileinfo.len = 0; + qq_pme->qq_state = QQ_STATE_INIT; + break; + } + if(qq_pme->fileinfo.len > 0) + { + if(qq_pme->fileinfo.len < TCPFILE_HDR_LEN04+1) //жʱҪݳȴͷ + { + need_len = TCPFILE_HDR_LEN04+1 - qq_pme->fileinfo.len; + if(datalen < need_len) + { + if(save_initial_tcp_data(&qq_pme->fileinfo, data, datalen, qq_pme->thread_id) < 0) + { + return APP_STATE_DROPME; + } + return APP_STATE_GIVEME; + } + memcpy(qq_pme->fileinfo.buf+qq_pme->fileinfo.len, data, need_len); + qq_pme->fileinfo.len += need_len; + data += need_len; + datalen -= need_len; + if(data_hit_feature(qq_pme->fileinfo.buf, qq_pme->fileinfo.len, 0, FINDEX_TCPFILE)) + { + qq_pme->fileinfo.prot_flag = QQ_FILECONT; + } + else if(data_hit_feature(qq_pme->fileinfo.buf, qq_pme->fileinfo.len, 0, FINDEX_TCPFILE_END)) + { + qq_pme->fileinfo.prot_flag = QQ_FILECONT_END; + } + else + { + return APP_STATE_DROPME; + } + if(*(qq_pme->fileinfo.buf) == TCPFILE_START_CHAR04) + { + qq_pme->fileinfo.block_len = ntohs(*((unsigned short *)&qq_pme->fileinfo.buf[3])); + qq_pme->compress_flag = qq_pme->fileinfo.buf[TCPFILE_HDR_LEN04-1]; + } + } + + //һij + need_len = qq_pme->fileinfo.block_len - qq_pme->fileinfo.len; + if(need_len > datalen) + { + if(save_initial_tcp_data(&qq_pme->fileinfo, data, datalen, qq_pme->thread_id) < 0) + { + return APP_STATE_DROPME; + } + return APP_STATE_GIVEME; + } + if(save_initial_tcp_data(&qq_pme->fileinfo, data, need_len, qq_pme->thread_id) < 0) + { + return APP_STATE_DROPME; + } + qq_pme->fileinfo.len = 0; + data += need_len; + datalen -= need_len; + + if(*(qq_pme->fileinfo.buf) == TCPFILE_START_CHAR04 && qq_pme->fileinfo.block_len>TCPFILE_HDR_LEN04) + { + if(*(qq_pme->fileinfo.buf + qq_pme->fileinfo.block_len - 1) != TCPFILE_END_CHAR04) + return APP_STATE_DROPME; + rec = protocol_process(qq_pme, qq_pme->fileinfo.prot_flag, qq_pme->fileinfo.buf+TCPFILE_HDR_LEN04, qq_pme->fileinfo.block_len-TCPFILE_HDR_LEN04-1, a_tcp, raw_pkt); + } + if(rec & APP_STATE_DROPME) + { + return rec; + } + } + + while(datalen>0) + { + //ͷȲ + if(datalen < TCPFILE_HDR_LEN04+1) + { + if(save_initial_tcp_data(&qq_pme->fileinfo, data, datalen, qq_pme->thread_id) < 0) + { + return APP_STATE_DROPME; + } + return APP_STATE_GIVEME; + } + + if(data_hit_feature(data, datalen, 0, FINDEX_TCPFILE)) + { + qq_pme->fileinfo.prot_flag = QQ_FILECONT; + } + else if(data_hit_feature(data, datalen, 0, FINDEX_TCPFILE_END)) + { + qq_pme->fileinfo.prot_flag = QQ_FILECONT_END; + } + else + { + //еʱ򿴵мС飬轫߳ + unsigned short block_len = ntohs(*((unsigned short *)&data[3])); + if(*data == TCPFILE_START_CHAR04 && block_len < TCPFILE_HDR_LEN04) + { + data += block_len; + datalen -= block_len; + } + else + { + return APP_STATE_DROPME; + } + } + + //ͷȹͷȡ鳤ȣ鲻Ҳ + if(*data == TCPFILE_START_CHAR04 && datalen>TCPFILE_HDR_LEN04) + { + qq_pme->fileinfo.block_len = ntohs(*((unsigned short *)&data[3])); + qq_pme->compress_flag = data[TCPFILE_HDR_LEN04-1]; + if(datalen < qq_pme->fileinfo.block_len) + { + if(save_initial_tcp_data(&qq_pme->fileinfo, data, datalen, qq_pme->thread_id) < 0) + { + return APP_STATE_DROPME; + } + return APP_STATE_GIVEME; + } + + rec = protocol_process(qq_pme, qq_pme->fileinfo.prot_flag, data+TCPFILE_HDR_LEN04, qq_pme->fileinfo.block_len-TCPFILE_HDR_LEN04-1, a_tcp, raw_pkt); + if(rec & APP_STATE_DROPME) + { + return rec; + } + data += qq_pme->fileinfo.block_len; + datalen -= qq_pme->fileinfo.block_len; + } + } + break; + + case QQ_STATE_FCONT_END: + case QQ_STATE_FCONT: + case QQ_STATE_INIT: + default: + break; + } + + return APP_STATE_GIVEME; +} + +extern "C" char QQ_PROT_TCP_ENTRY(struct streaminfo *a_tcp, void **pme, int thread_seq,const void *raw_pkt) +{ + QQ_PACKET_TYPE_t type; + qq_proto_pme_t *qq_pme=(qq_proto_pme_t*)(*pme); + int rec = APP_STATE_GIVEME; + + switch(a_tcp->opstate) + { + case OP_STATE_PENDING: + type = is_qq_protocol_tcp((char *)a_tcp->ptcpdetail->pdata, a_tcp->ptcpdetail->datalen); + if(type) + { + if(init_qq_pme_info(&qq_pme, a_tcp->threadnum, 1)) + return APP_STATE_DROPME; + qq_pme->qq_state = assign_qq_state(type); + *pme = qq_pme; + } + else + { + return APP_STATE_DROPME; + } + //no break here + + case OP_STATE_DATA: + qq_pme->qq_state = analyse_tcp_pdata_state(qq_pme->qq_state, (char *)a_tcp->ptcpdetail->pdata, a_tcp->ptcpdetail->datalen); + + rec = process_tcp_data_state(a_tcp, qq_pme, thread_seq, raw_pkt); + break; + + case OP_STATE_CLOSE: + clear_qq_pme_info(qq_pme, a_tcp, raw_pkt); + break; + + default: + return APP_STATE_DROPME; + } + + if(rec & APP_STATE_DROPME) + { + clear_qq_pme_info(qq_pme, a_tcp, raw_pkt); + } + + return rec; +} + +int mkdir_according_path(const char * path) +{ + char buffer[256]; + const char *ps=path, *pc; + + if(*ps == '/') + ps += 1; + + while((pc = strchr(ps, '/')) != NULL) + { + while(*(pc+1) == '/') + pc++; + + memcpy(buffer, path, pc - path); + buffer[pc-path] = '\0'; + + if(access(buffer, F_OK)) + { + if(mkdir(buffer, 0777)) + { + return -1; + } + } + + ps = pc + 1; + } + if(access(path, F_OK)) + { + if(mkdir(path, 0777)) + { + return -1; + } + } + return 0; +} + +static int register_field_stat(const char *logpath) +{ + unsigned int stat_cycle; + int ret, i; + char stat_log[128]; + const char *region_name[STAT_ID_NUM]={"NEW_SESSION", "DEL_SESSION", "SESSION_NUM"}; + + snprintf(stat_log, 128, "%s/qq_stat.log", logpath); + + ret = MESA_load_profile_uint_def(CONF_FILENAME, "MODULE", "STAT_FIELD_CYCLE",&stat_cycle, 5); + if(ret < 0) + { + MESA_HANDLE_RUNTIME_LOG(g_qq_global_info.runtime_log, RLOG_LV_INFO, MODULE_NAME,"get [MODULE] STAT_FIELD_CYCLE failed, using default 5."); + } + ret = MESA_load_profile_int_def(CONF_FILENAME, "MODULE", "STAT_FIELD_TRIG",&g_qq_global_info.stat_trig, 0); + if(ret < 0) + { + MESA_HANDLE_RUNTIME_LOG(g_qq_global_info.runtime_log, RLOG_LV_INFO, MODULE_NAME,"get [MODULE] STAT_FIELD_TRIG failed, using default 0."); + } + + if(g_qq_global_info.stat_trig==0) + return 0; + + FILE* stat_fd = fopen(stat_log, "w"); + if(stat_fd == NULL) + { + MESA_HANDLE_RUNTIME_LOG(g_qq_global_info.runtime_log, RLOG_LV_INFO, MODULE_NAME,"fopen %s failed.", stat_log); + return -1; + } + + g_qq_global_info.stat_handle = init_screen_stat(stat_fd, stat_cycle, g_qq_global_info.stat_trig); + if(g_qq_global_info.stat_handle==NULL) + { + MESA_HANDLE_RUNTIME_LOG(g_qq_global_info.runtime_log, RLOG_LV_INFO, MODULE_NAME,"init_screen_stat failed."); + return -1; + } + + for(i=0;i= 0); + + srand(time(NULL)); + return 0; +} + +extern "C" void QQ_PROT_DESTROY(void) +{ +} + diff --git a/src/qq_file_entry.h b/src/qq_file_entry.h new file mode 100644 index 0000000..23e6a32 --- /dev/null +++ b/src/qq_file_entry.h @@ -0,0 +1,125 @@ +#ifndef __QQ_FILE_ENTRY_H__ +#define __QQ_FILE_ENTRY_H__ + +#include + +#include + +#define CONF_FILENAME "./conf/qq_file_trans.conf" +#define QQ_DEBUG_FILEPATH "./qq_files" +#define MODULE_NAME "QQ_FILE" + +#define MAX_QQ_FEATURE_NUM 16 +#define MAX_AND_RULE 32 + +#define PACKET_MIN_LEN_QQNUM 16 +#define PACKET_MIN_LEN_TCPNAME 551 +#define PACKET_MIN_LEN_UDPNAME 535 + +#define TCPFILE_START_CHAR04 0x04 +#define TCPFILE_END_CHAR04 0x03 +#define TCPFILE_HDR_LEN04 53 + +#define TCPFILE_START_CHAR0c 0x0c +#define TCPFILE_HDR_LEN0c 22 + +typedef enum __QQ_PACKET_TYPE +{ + QQ_PACKET_NOT=0, + QQ_PACKET_QQNUM, + QQ_PACKET_TCPFILE, + QQ_PACKET_TCPFILENAME, + QQ_PACKET_UDPFILE, + QQ_PACKET_UDPFILE_END, + QQ_PACKET_UDPFILENAME, + QQ_PACKET_OTHER, +}QQ_PACKET_TYPE_t; + +typedef enum __QQ_STATE +{ + QQ_STATE_INIT=0, + QQ_STATE_QQNUM, + QQ_STATE_FNAME, + QQ_STATE_FCONT_START, + QQ_STATE_FCONT, + QQ_STATE_FCONT_END, +}QQ_STATE_t; + +typedef enum __FEATURE_INDEX +{ + FINDEX_TCPPROT=0, + FINDEX_TCPNUM, + FINDEX_TCPNAME, + FINDEX_TCPFILE, + FINDEX_TCPFILE_END, + FINDEX_UDPPROT, + FINDEX_UDPNUM, + FINDEX_UDPNAME, + FINDEX_UDPFILE, + FINDEX_UDPFILE_END, + + FINDEX_NUM, +}FEATURE_INDEX_T; + +enum __FIELD_STAT_ID +{ + STAT_ID_NEW_SESSION, + STAT_ID_DEL_SESSION, + STAT_ID_SESSION_NUM, + STAT_ID_NUM, +}; + +typedef struct __trans_file_info +{ + char *buf; + unsigned int len; + unsigned int max_len; + long long prot_flag; + + int block_seq; //ݰţʱشUDP + unsigned short block_len; //һСĴСһһĴСTCP + unsigned short file_seq; //һСĴСһһĴСTCP +}trans_file_info_t; + +typedef struct __qq_proto_pme +{ + void *connector_hdl; + char filename[512]; + int filename_len; + QQ_STATE_t qq_state; + unsigned int qqnum[2]; + unsigned int qqnum_from; + unsigned int qqnum_to; + + trans_file_info_t fileinfo; + + int thread_id; + unsigned int file_dir; + unsigned int total_file_len; + unsigned int curr_file_len; + char pending_flag; + char end_flag; + char compress_flag; + char tcp_flag; + unsigned int random; +}qq_proto_pme_t; + +typedef struct __qq_global_info +{ + void *runtime_log; + void *stat_handle; + docanalyze_instance_t instanse; + char *feature[FINDEX_NUM][MAX_QQ_FEATURE_NUM][MAX_AND_RULE]; + unsigned int ftlen[FINDEX_NUM][MAX_QQ_FEATURE_NUM][MAX_AND_RULE]; + unsigned int ftoff[FINDEX_NUM][MAX_QQ_FEATURE_NUM][MAX_AND_RULE]; + unsigned int rulenum[FINDEX_NUM][MAX_QQ_FEATURE_NUM]; //ÿһڲ + unsigned int fnum[FINDEX_NUM]; + + int project_id; + int stat_trig; + int stat_id[STAT_ID_NUM]; + int debug_sw; +}qq_global_info_t; + +#endif + diff --git a/src/qq_file_global.c b/src/qq_file_global.c new file mode 100644 index 0000000..ce74f1c --- /dev/null +++ b/src/qq_file_global.c @@ -0,0 +1,308 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "qq_file_entry.h" +#include "qq_file_global.h" +#include "connector.h" + +#define QQ_OPT_SERVICE "SERVICE_IMQQ" +#define QQ_OPT_FILESET "opt_file_set" +#define QQ_OPT_FILENAME "opt_file_name" +#define QQ_OPT_FILECONT "opt_file_content" +#define QQ_OPT_NUMFROM "opt_im_from" +#define QQ_OPT_NUMTO "opt_im_to" +#define QQ_OPT_ACCOUNT "opt_im_account" + +extern qq_global_info_t g_qq_global_info; +const unsigned char gzip_feature[4]={0x1f, 0x8b, 0x08, 0x00}; + +int write_file_cont2disk(char *buffer, int filelen, char *filename, int seq, int random) +{ + FILE *fp; + int writelen, offset=0; + char filenamestr[512]; + + sprintf(filenamestr, "%s/%d_%u_%s", QQ_DEBUG_FILEPATH, seq, random, filename); + + fp = fopen(filenamestr, "ab+"); + if(fp == NULL) + { + printf("fopen file %s failed.\n", filenamestr); + return -1; + } + + while(offset < filelen) + { + writelen = fwrite(buffer + offset, 1, filelen - offset, fp); + if(writelen < 0) + { + printf("read error: %s\n", strerror(errno)); + return -1; + } + + offset += writelen; + } + fclose(fp); + return 0; +} + +int buf_cache_check_size(trans_file_info_t *pdstBuf, int wantedlen, int thread_seq) +{ + int ret=0, needlen, block_num=0; + + if(pdstBuf->max_len > wantedlen + pdstBuf->len) + return 0; + + needlen = wantedlen + pdstBuf->len - pdstBuf->max_len; + block_num = needlen/REALLOC_BLOCK_SIZE; + if(needlen%REALLOC_BLOCK_SIZE) + block_num += 1; + + pdstBuf->max_len += block_num*REALLOC_BLOCK_SIZE; + + if(pdstBuf->max_len > MAX_MALLOC_SIZE) + { + pdstBuf->max_len -= block_num*REALLOC_BLOCK_SIZE; + return -1; + } + + if(pdstBuf->buf == NULL) + { + pdstBuf->buf = (char *)dictator_malloc(thread_seq, pdstBuf->max_len); + } + else + { + pdstBuf->buf = (char *)dictator_realloc(thread_seq, pdstBuf->buf, pdstBuf->max_len); + ret = 1; + } + + return ret; +} + +int save_initial_tcp_data(trans_file_info_t *pdstBuf, char *data, int datalen, int thread_seq) +{ + if(buf_cache_check_size(pdstBuf, datalen, thread_seq) < 0) + { + return -1; + } + memcpy(pdstBuf->buf+pdstBuf->len, data, datalen); + pdstBuf->len += datalen; + + return 0; +} + + +int convert_from_unicode2utf8(char *in, int in_len, char *out, int *out_len) +{ + iconv_t cd; + size_t inlen = in_len, outlen=*out_len, ret; + + cd = iconv_open("utf-8", "unicode"); + if(cd == (iconv_t)-1) + { + return -1; + } + ret = iconv(cd, &in, &inlen, &out, &outlen); + if(ret == (size_t)-1) + { + iconv_close(cd); + return -1; + } + iconv_close(cd); + *out_len = outlen; + + return 0; +} + +int sendback_qq_data(qq_proto_pme_t *qq_pme, struct streaminfo *a_udp, char *filecont, int contlen) +{ + int nest_opt_num = 1; + void *nested_opt_handle, *nested_opt_unit_handle, *simple_opt=NULL; + + if(qq_pme->connector_hdl == NULL) + { + appd_basic_t basic; + ulong64 streamid[1]; + char qqfrom[32], qq_to[32]; + + streamid[0] = project_req_get_ulong(a_udp, g_qq_global_info.project_id); + + basic.addr = (struct ipaddr*)&a_udp->addr; + basic.addr_num = 1; + basic.appd_type = APPD_SENDBACK; + basic.destination = DEST_APPD; + basic.service_name = QQ_OPT_SERVICE; + basic.streamid = streamid; + basic.streamid_num = 1; + + qq_pme->connector_hdl = connector_start(&basic, a_udp); + if(qq_pme->connector_hdl == NULL) + return APP_STATE_DROPME; + + if(qq_pme->filename_len > 0) + { + nest_opt_num = 2; + } + sprintf(qqfrom, "%u", qq_pme->qqnum_from); + sprintf(qq_to, "%u", qq_pme->qqnum_to); + + simple_opt = connector_create_simple_opt(3); + connector_append_simple_opt(simple_opt, QQ_OPT_NUMFROM,qqfrom, strlen(qqfrom)); + connector_append_simple_opt(simple_opt, QQ_OPT_ACCOUNT,qqfrom, strlen(qqfrom)); + connector_append_simple_opt(simple_opt, QQ_OPT_NUMTO,qq_to, strlen(qq_to)); + connector(qq_pme->connector_hdl, COMPLETE, simple_opt, NULL); + connector_free_simple_opt(&simple_opt); + } + + nested_opt_handle = connector_create_nested_opt(1); + nested_opt_unit_handle = connector_create_nested_opt_unit(QQ_OPT_FILESET, nest_opt_num); + if(nest_opt_num == 2) + { + connector_append_nested_opt_unit(nested_opt_unit_handle, QQ_OPT_FILENAME,qq_pme->filename, qq_pme->filename_len); + } + connector_append_nested_opt_unit(nested_opt_unit_handle, QQ_OPT_FILECONT,filecont, contlen); + connector_append_nested_opt(nested_opt_handle,nested_opt_unit_handle); + + if(qq_pme->end_flag) + { + connector(qq_pme->connector_hdl, FRAG_END, NULL, nested_opt_handle); + connector_finish(qq_pme->connector_hdl); + qq_pme->connector_hdl = NULL; + } + else + { + connector(qq_pme->connector_hdl, FRAG, NULL, nested_opt_handle); + } + connector_free_nested_opt_unit(&nested_opt_unit_handle); + connector_free_nested_opt(&nested_opt_handle); + + return APP_STATE_GIVEME; +} + +int protocol_process(qq_proto_pme_t *qq_pme, long long prot_flag, char *buf_in, int inlen, struct streaminfo *a_udp, const void *raw_pkt) +{ + int rec = APP_STATE_GIVEME; + char buffer[512]={0}, *buf=buf_in; + int outlen=512, ret, buflen=inlen, k; + result_array_t result_array; + + switch(prot_flag) + { + case QQ_FILENAME: + if(qq_pme->pending_flag==0) + break; + else + { + qq_pme->fileinfo.block_seq = -1; //ݿ¼ + qq_pme->end_flag = 0; + qq_pme->pending_flag = 0; + qq_pme->fileinfo.file_seq += 1; + + if(qq_pme->qqnum_from == 0) + { + qq_pme->qqnum_to = qq_pme->qqnum[qq_pme->file_dir]; + if(qq_pme->qqnum_to == qq_pme->qqnum[0]) + qq_pme->qqnum_from = qq_pme->qqnum[1]; + else + qq_pme->qqnum_from = qq_pme->qqnum[0]; + } + + if(g_qq_global_info.debug_sw) + { + qq_pme->random = rand(); + } + } + if(!convert_from_unicode2utf8(buf_in, inlen, buffer, &outlen)) + { + snprintf(qq_pme->filename, sizeof(qq_pme->filename), "%s", buffer); + qq_pme->filename_len = strlen(qq_pme->filename); + MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_DEBUG, MODULE_NAME, "DETECT_QQ_FILE %s, QQ_FROM: %u, QQ_TO: %u, FILE_LEN: %u, FILENAME: %s", \ + qq_pme->tcp_flag?"TCP":"UDP", qq_pme->qqnum_from, qq_pme->qqnum_to, qq_pme->total_file_len,qq_pme->filename); + } + else + { + MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_INFO, MODULE_NAME, "convert_from_unicode2utf8 error: %s\n", strerror(errno)); + return APP_STATE_DROPME; + } + break; + + case QQ_FILECONT_END: + case QQ_FILECONT: + if(qq_pme->filename_len == 0) + return APP_STATE_DROPME; + + if(prot_flag==QQ_FILECONT_END) + { + if(qq_pme->end_flag || qq_pme->pending_flag) + break; + else + { + qq_pme->end_flag = 1; + qq_pme->pending_flag = 1; + } + } + else if(qq_pme->pending_flag) + { + qq_pme->end_flag = 0; + qq_pme->pending_flag = 0; + } + + if(inlen >= 4 && !memcmp(buf_in, gzip_feature, 4) && qq_pme->compress_flag) + { + docanalyze_streamparam_t doc_hanlde = docanalyze_startstream(DOC_GZIP_TYPE, g_qq_global_info.instanse, qq_pme->thread_id); + if(doc_hanlde ==NULL) + { + MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_DEBUG, MODULE_NAME, "docanalyze_startstream() error."); + return APP_STATE_GIVEME; + } + memset(&result_array, 0, sizeof(result_array_t)); + ret = docanalyze_parsestream(doc_hanlde, buf_in, inlen, &result_array); + if(ret == DOC_PRO_OK) + { + for (k=0; k < result_array.result_num; k++) + { + buf = result_array.result_buff[k].presult; + buflen = result_array.result_buff[k].size; + } + } + qq_pme->curr_file_len += buflen; + + if(g_qq_global_info.debug_sw) + { + write_file_cont2disk(buf, buflen, qq_pme->filename, qq_pme->fileinfo.file_seq, qq_pme->random); + } + rec = sendback_qq_data(qq_pme, a_udp, buf, buflen); + + docanalyze_freeresult(&result_array); + docanalyze_endstream(doc_hanlde); + } + else + { + qq_pme->curr_file_len += buflen; + + if(g_qq_global_info.debug_sw) + { + write_file_cont2disk(buf, buflen, qq_pme->filename, qq_pme->fileinfo.file_seq, qq_pme->random); + } + rec = sendback_qq_data(qq_pme, a_udp, buf, buflen); + } + break; + + default: break; + } + + return rec; +} + diff --git a/src/qq_file_global.h b/src/qq_file_global.h new file mode 100644 index 0000000..2f1ad94 --- /dev/null +++ b/src/qq_file_global.h @@ -0,0 +1,21 @@ +#ifndef __QQ_FILE_GLOBAL_H__ +#define __QQ_FILE_GLOBAL_H__ + +#define QQ_FILENAME 1 +#define QQ_FILECONT 2 +#define QQ_FILECONT_END 4 + +#define MAX_MALLOC_SIZE (16*1024) +#define REALLOC_BLOCK_SIZE 1024 + +#define MESA_HANDLE_RUNTIME_LOGV2(handle, lv, mod, fmt, args...) \ + MESA_handle_runtime_log((handle), (lv), (mod), "%s:%d, " fmt, \ + __FILE__, __LINE__, ##args) + +int buf_cache_check_size(trans_file_info_t *pdstBuf, int wantedlen, int thread_seq); +int save_initial_tcp_data(trans_file_info_t *pdstBuf, char *data, int datalen, int thread_seq); + +int protocol_process(qq_proto_pme_t *qq_pme, long long prot_flag, char *buf, int buflen, struct streaminfo *a_udp, const void *raw_pkt); + +#endif +