diff --git a/common/include/kni_utils.h b/common/include/kni_utils.h index b422b08..0067546 100644 --- a/common/include/kni_utils.h +++ b/common/include/kni_utils.h @@ -48,6 +48,7 @@ do { \ snprintf(location, KNI_PATH_MAX, "%s: line %d", __FILE__, __LINE__); \ MESA_handle_runtime_log(handler, RLOG_LV_DEBUG, location, fmt, ##__VA_ARGS__); } while(0) + //default tcp opt #define KNI_DEFAULT_WINSCLE 0 #define KNI_DEFAULT_MSS 1460 @@ -61,6 +62,30 @@ struct kni_tcpopt_info{ uint8_t sack; }; +//field_stat +#define KNI_FIELD_MAX 24 +enum kni_field{ + KNI_FIELD_TOT_PKT, + KNI_FIELD_BYP_PKT, + KNI_FIELD_INTCP_PKT, + KNI_FIELD_IPV6_PKT, + KNI_FIELD_NULL_PKT, + KNI_FIELD_NO_SYN_EXP, + KNI_FIELD_NO_SA_EXP, + KNI_FIELD_UNKNOWN_STATE_EXP, + KNI_FIELD_TOT_STM, + KNI_FIELD_BYP_STM, + KNI_FIELD_INTCP_STM, + KNI_FIELD_SSL_STM, + KNI_FIELD_HTTP_STM, + KNI_FIELD_UNKNOWN_STM, +}; + +struct kni_field_stat_handle{ + screen_stat_handle_t handle; + int fields[KNI_FIELD_MAX]; +}; + uint16_t kni_ip_checksum(const void *buf, size_t hdr_len); uint16_t kni_tcp_checksum(const void *_buf, size_t len, in_addr_t src_addr, in_addr_t dest_addr); uint16_t kni_udp_checksum(const void *_buf, size_t len, in_addr_t src_addr, in_addr_t dest_addr); diff --git a/entry/src/kni_entry.cpp b/entry/src/kni_entry.cpp index 56ffeec..c0b1887 100644 --- a/entry/src/kni_entry.cpp +++ b/entry/src/kni_entry.cpp @@ -21,7 +21,9 @@ extern int g_iThreadNum; //一个tcp流中有多个http,ssl会话的情况,只扫描第一个 -struct kni_handle *g_kni_handle; +struct kni_handle *g_kni_handle = NULL; +struct kni_field_stat_handle *g_kni_fs_handle = NULL; + //int g_http_project_id; //struct kni_marsio_handle *g_kni_marsio_handle; //g_iThreadNum 为sapp线程数 @@ -176,12 +178,17 @@ static int send_to_tfe(struct kni_marsio_handle *handle, char *raw_data, int raw static char pending_opstate(const struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo){ void *logger = g_kni_handle->logger; + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_TOT_STM], 0, FS_OP_ADD, 1); if(!pktinfo->tcphdr->syn){ //TODO: pending_opstate 不是syn, bypass这个流 KNI_LOG_ERROR(logger, "pending opstate: not syn"); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_NO_SYN_EXP], 0, FS_OP_ADD, 1); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_STM], 0, FS_OP_ADD, 1); return APP_STATE_FAWPKT | APP_STATE_DROPME; } pmeinfo->client_tcpopt = kni_get_tcpopt(pktinfo->tcphdr, pktinfo->tcphdr_len); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1); return APP_STATE_FAWPKT | APP_STATE_GIVEME; } @@ -203,6 +210,7 @@ static char data_opstate(const struct streaminfo *stream, struct pme_info *pmein //action取值只能为 KNI_ACTION_INTERCEPT, KNI_ACTION_UNKNOWN, 因为判断是KNI_ACTION_BYPASS之后直接返回 APP_STATE_DROPME了 if(pmeinfo->action == KNI_ACTION_INTERCEPT){ send_to_tfe(g_kni_handle->marsio_handle, buf, len, thread_seq); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_PKT], 0, FS_OP_ADD, 1); return APP_STATE_DROPPKT | APP_STATE_GIVEME; } //TODO: client hello如果跨包怎么办?client hello后面一个包先到,这个包该丢掉还是bypass @@ -210,15 +218,19 @@ static char data_opstate(const struct streaminfo *stream, struct pme_info *pmein // syn/ack包 if(pktinfo->tcphdr->syn && pktinfo->tcphdr->ack){ pmeinfo->server_tcpopt = kni_get_tcpopt(pktinfo->tcphdr, pktinfo->tcphdr_len); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1); return APP_STATE_FAWPKT | APP_STATE_GIVEME; } if(pktinfo->data_len <= 0){ + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1); return APP_STATE_FAWPKT | APP_STATE_GIVEME; } //第一个数据包: 如果从第一个数据包判断不出协议,直接返回,后续包也不要了 //单向流, 直接bypass if(stream->dir != DIR_DOUBLE){ KNI_LOG_INFO(logger, "stream dir is %d, bypass", stream->dir); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_STM], 0, FS_OP_ADD, 1); return APP_STATE_FAWPKT | APP_STATE_DROPME; } struct protocol_identify_result *result = ALLOC(struct protocol_identify_result, 1); @@ -227,42 +239,64 @@ static char data_opstate(const struct streaminfo *stream, struct pme_info *pmein if(pmeinfo->protocol == KNI_PROTOCOL_UNKNOWN){ KNI_LOG_INFO(logger, "Failed at protocol_identify, protocol is %d\n", pmeinfo->protocol); FREE(&result); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_STM], 0, FS_OP_ADD, 1); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_UNKNOWN_STM], 0, FS_OP_ADD, 1); return APP_STATE_FAWPKT | APP_STATE_DROPME; } //protocol = KNI_PROTOCOL_SSL/KNI_PROTOCOL_HTTP, 判断action, action返回值: KNI_ACTION_INTERCEPT/KNI_ACTION_BYPASS + if(pmeinfo->protocol == KNI_PROTOCOL_SSL){ + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_SSL_STM], 0, FS_OP_ADD, 1); + } + if(pmeinfo->protocol == KNI_PROTOCOL_HTTP){ + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_HTTP_STM], 0, FS_OP_ADD, 1); + } pmeinfo->action = get_action((struct ipaddr*)(&stream->addr), result->domain, result->domain_len, thread_seq); FREE(&result); if(pmeinfo->action == KNI_ACTION_BYPASS){ + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_STM], 0, FS_OP_ADD, 1); return APP_STATE_FAWPKT | APP_STATE_DROPME; } //TODO: 这块比较奇怪, 收到client hello, 但是没有syn/ack包, 直接bypass了 if(pmeinfo->client_tcpopt == NULL || pmeinfo->server_tcpopt == NULL){ KNI_LOG_ERROR(logger, "Failed at intercept, %s, %s", pmeinfo->client_tcpopt == NULL ? "no syn" : "", pmeinfo->server_tcpopt == NULL ? "no syn/ack" : ""); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_NO_SA_EXP], 0, FS_OP_ADD, 1); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_STM], 0, FS_OP_ADD, 1); return APP_STATE_FAWPKT | APP_STATE_DROPME; } //action = KNI_ACTION_INTERCEPT, 带上控制信息发送给qq, 要修改ip, tcp的校验和 buf = tcp_restore_info_header_add(pmeinfo, pktinfo, &len); send_to_tfe(g_kni_handle->marsio_handle, buf, len, thread_seq); FREE(&buf); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_PKT], 0, FS_OP_ADD, 1); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_STM], 0, FS_OP_ADD, 1); return APP_STATE_DROPPKT | APP_STATE_GIVEME; } static char close_opstate(){ + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1); return APP_STATE_FAWPKT | APP_STATE_DROPME; } //从syn包开始回调 extern "C" char kni_tcpall_entry(const struct streaminfo* stream, void** pme, int thread_seq, const void* a_packet){ void *logger = g_kni_handle->logger; - KNI_LOG_DEBUG(logger, "call kni_tcpall_entry"); + //KNI_LOG_DEBUG(logger, "call kni_tcpall_entry"); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_TOT_PKT], 0, FS_OP_ADD, 1); //当前包bypass, 剩下包bypass //TODO: ipv6暂时不处理, ipv6: 通过nexthdr链式寻找tcp头(IPPROTO_TCP) if(stream->addr.addrtype == ADDR_TYPE_IPV6){ + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_IPV6_PKT], 0, FS_OP_ADD, 1); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1); return APP_STATE_FAWPKT | APP_STATE_DROPME; } //a_packet == NULL, 不处理这个包 if(a_packet == NULL){ + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_NULL_PKT], 0, FS_OP_ADD, 1); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1); return APP_STATE_FAWPKT | APP_STATE_GIVEME; } struct pme_info *pmeinfo = *(struct pme_info **)pme; @@ -275,7 +309,7 @@ extern "C" char kni_tcpall_entry(const struct streaminfo* stream, void** pme, in pktinfo->tcphdr_len = pktinfo->tcphdr->doff * 4; pktinfo->data = (char*)pktinfo->tcphdr + pktinfo->tcphdr_len; pktinfo->data_len = pktinfo->ip_totlen - pktinfo->iphdr_len - pktinfo->tcphdr_len; - int ret = APP_STATE_FAWPKT | APP_STATE_DROPME; + int ret; switch(stream->pktstate){ case OP_STATE_PENDING: *pme = pmeinfo = pme_info_new(); @@ -288,6 +322,10 @@ extern "C" char kni_tcpall_entry(const struct streaminfo* stream, void** pme, in ret = close_opstate(); break; default: + ret = APP_STATE_FAWPKT | APP_STATE_GIVEME; + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_UNKNOWN_STATE_EXP], 0, FS_OP_ADD, 1); + KNI_LOG_ERROR(logger, "Unknown stream opstate %d", stream->pktstate); break; } FREE(&pktinfo); @@ -386,6 +424,50 @@ static struct kni_marsio_handle* kni_marsio_init(const char* profile){ return handle; } +static struct kni_field_stat_handle * fs_init(const char *profile){ + void *logger = g_kni_handle->logger; + const char *section = "field_stat"; + char stat_path[KNI_PATH_MAX]; + MESA_load_profile_string_def(profile, section, "stat_path", stat_path, KNI_PATH_MAX, "./fs2_kni.status"); + KNI_LOG_INFO(logger, "MESA_prof_load, [%s]:\n stat_path: %s\n", "field_stat", stat_path); + screen_stat_handle_t handle = FS_create_handle(); + if(handle == NULL){ + KNI_LOG_ERROR(logger, "Failed at create FS_create_handle"); + return NULL; + } + const char* app_name = "fs2_kni"; + FS_set_para(handle, APP_NAME, app_name, strlen(app_name) + 1); + FS_set_para(handle, OUTPUT_DEVICE, stat_path, strlen(stat_path)+1); + int value=0; + FS_set_para(handle, FLUSH_BY_DATE, &value, sizeof(value)); + value=1; + FS_set_para(handle, PRINT_MODE, &value, sizeof(value)); + value=1; + FS_set_para(handle, CREATE_THREAD, &value, sizeof(value)); + value=5; + FS_set_para(handle, STAT_CYCLE, &value, sizeof(value)); + value=4096; + FS_set_para(handle, MAX_STAT_FIELD_NUM, &value, sizeof(value)); + struct kni_field_stat_handle *fs_handle = ALLOC(struct kni_field_stat_handle, 1); + fs_handle->handle = handle; + fs_handle->fields[KNI_FIELD_TOT_PKT] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "tot_pkt"); + fs_handle->fields[KNI_FIELD_BYP_PKT] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "byp_pkt"); + fs_handle->fields[KNI_FIELD_INTCP_PKT] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "intcp_pkt"); + fs_handle->fields[KNI_FIELD_IPV6_PKT] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "ipv6_pkt"); + fs_handle->fields[KNI_FIELD_NULL_PKT] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "null_pkt"); + fs_handle->fields[KNI_FIELD_NO_SYN_EXP] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "no_syn_pkt"); + fs_handle->fields[KNI_FIELD_UNKNOWN_STATE_EXP] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "unknown_state"); + fs_handle->fields[KNI_FIELD_NO_SA_EXP] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "no_s/a_pkt"); + fs_handle->fields[KNI_FIELD_TOT_STM] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "tot_stm"); + fs_handle->fields[KNI_FIELD_BYP_STM] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "byp_stm"); + fs_handle->fields[KNI_FIELD_INTCP_STM] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "intcp_stm"); + fs_handle->fields[KNI_FIELD_SSL_STM] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "ssl_stm"); + fs_handle->fields[KNI_FIELD_HTTP_STM] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "http_stm"); + fs_handle->fields[KNI_FIELD_UNKNOWN_STM] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "unknown_stm"); + return fs_handle; +} + + extern "C" int kni_init(){ g_kni_handle = ALLOC(struct kni_handle, 1); const char *profile = "./conf/kni/kni.conf"; @@ -408,7 +490,7 @@ extern "C" int kni_init(){ //init http_project int id = http_project_init(); if(id < 0){ - KNI_LOG_ERROR(logger, "Failed at http_project_init, exit. ret is %d", id); + KNI_LOG_ERROR(logger, "Failed at init http project, exit. ret is %d", id); exit(EXIT_FAILURE); } g_kni_handle->http_project_id = id; @@ -416,15 +498,23 @@ extern "C" int kni_init(){ //init marsio g_kni_handle->marsio_handle = kni_marsio_init(profile); if(g_kni_handle->marsio_handle == NULL){ - KNI_LOG_ERROR(logger, "Failed at kni_marsio_init, exit"); + KNI_LOG_ERROR(logger, "Failed at init marsio, exit"); exit(EXIT_FAILURE); } //init maat g_kni_handle->maat_handle = kni_maat_init(profile, logger); if(g_kni_handle->maat_handle == NULL){ - KNI_LOG_ERROR(logger, "Failed at kni_maat_init, exit"); + KNI_LOG_ERROR(logger, "Failed at init maat, exit"); exit(EXIT_FAILURE); } + + //init_filedstat + struct kni_field_stat_handle *fs_handle = fs_init(profile); + if(fs_handle == NULL){ + KNI_LOG_ERROR(logger, "Failed at init field_stat"); + } + g_kni_fs_handle = fs_handle; + return 0; } \ No newline at end of file