This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
tango-kni/entry/src/kni_entry.cpp
2019-05-18 12:41:31 +08:00

520 lines
23 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "kni_utils.h"
#include "ssl_utils.h"
#include "kni_entry.h"
#include "marsio.h"
#include "kni_maat.h"
#include "MESA/http.h"
extern int g_iThreadNum;
//APP_STATE_DROPME/GIVEME: 当前tcp会话的剩下包是否回调
//APP_STATE_FAWPKT/DROPPKT: 当前包是否丢弃or转发如果是丢弃当前包不会给后面的插件
//PROT_STATE_GIVEME/DROPME: 当前http会话的剩下包是否回调
//TODO: seq, ack 是当拿到client hello时传给秋秋取client hello的 seq, ack, 时间戳和sack没有解, 不用解只需要知道enable/disable即可
//TODO: 注意内存泄漏ALLOC对应的FREE, 还有calloc
//TOOD: 函数加static
//TODO: 统计syn/syn/ack个数流个数 pending not syn个数, not syn/ack个数, 单向流数量, 发往tfe的包数流数收到的包数流数
//多个tcpall插件APP_STATE_DROPPKT, APP_STATE_FAWPKT? 有一个droppkt就不给后面的插件了
//一个tcp流中有多个httpssl会话的情况只扫描第一个
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线程数
static struct pme_info* pme_info_new(){
struct pme_info* pmeinfo = ALLOC(struct pme_info, 1);
return pmeinfo;
}
static void pme_info_destroy(struct pme_info *pmeinfo){
if(pmeinfo != NULL){
if(pmeinfo->client_tcpopt != NULL){
FREE(&(pmeinfo->client_tcpopt));
}
if(pmeinfo->server_tcpopt != NULL){
FREE(&(pmeinfo->server_tcpopt));
}
FREE(&pmeinfo);
}
}
static int protocol_identify(const struct streaminfo* stream, char *buf, int len, struct protocol_identify_result *result){
//判断是http
struct http_project* project = (struct http_project*)project_req_get_struct(stream, g_kni_handle->http_project_id);
if(project != NULL){
result->protocol = KNI_PROTOCOL_HTTP;
result->domain_len = project->host_len;
memcpy(result->domain, project->host, result->domain_len);
return 0;
}
//判断是ssl
enum chello_parse_result chello_status = CHELLO_PARSE_INVALID_FORMAT;
struct ssl_chello *chello = NULL;
chello = ssl_chello_parse((const unsigned char*)buf, len, &chello_status);
if(chello_status == CHELLO_PARSE_SUCCESS){
result->protocol = KNI_PROTOCOL_SSL;
result->domain_len = strnlen(chello->sni, KNI_DOMAIN_MAX);
memcpy(result->domain, chello->sni, result->domain_len);
ssl_chello_free(chello);
return 0;
}
ssl_chello_free(chello);
result->protocol = KNI_PROTOCOL_UNKNOWN;
return 0;
}
static int tcp_restore_info_tlv_add(uint16_t type, uint16_t value_len, uint32_t value, char *header, int *offset, int *nr_tlvs){
int tlv_len = sizeof(tcp_restore_info_tlv) + value_len;
struct tcp_restore_info_tlv *tlv_info = (struct tcp_restore_info_tlv*)calloc(tlv_len, 1);
tlv_info->type= htons(type);
tlv_info->length = htons(tlv_len);
if(value_len == 1){
tlv_info->value_as_uint8[0] = value;
}
if(value_len == 2){
tlv_info->value_as_uint16[0] = value;
}
if(value_len == 4){
tlv_info->value_as_uint32[0] = value;
}
memcpy(header + *offset, tlv_info, tlv_len);
*offset += tlv_len;
(*nr_tlvs)++;
free(tlv_info);
return 0;
}
static struct tcp_restore_info_header* tcp_restore_info_header_new(struct pme_info *pmeinfo, struct pkt_info *pktinfo, int *len){
struct tcp_restore_info_header *header = (struct tcp_restore_info_header*)calloc(TCP_RESTORE_HEADER_MAX, 1);
int offset = sizeof(struct tcp_restore_info_header);
int nr_tlvs = 0;
tcp_restore_info_tlv_add(TCP_RESTORE_INFO_TLV_SEQ, 4, pktinfo->tcphdr->seq, (char*)header, &offset, &nr_tlvs);
tcp_restore_info_tlv_add(TCP_RESTORE_INFO_TLV_ACK, 4, pktinfo->tcphdr->ack_seq, (char*)header, &offset, &nr_tlvs);
tcp_restore_info_tlv_add(TCP_RESTORE_INFO_TLV_MSS_CLIENT, 2, htons(pmeinfo->client_tcpopt->mss), (char*)header, &offset, &nr_tlvs);
tcp_restore_info_tlv_add(TCP_RESTORE_INFO_TLV_MSS_SERVER, 2, htons(pmeinfo->server_tcpopt->mss), (char*)header, &offset, &nr_tlvs);
tcp_restore_info_tlv_add(TCP_RESTORE_INFO_TLV_WSACLE_CLIENT, 1, pmeinfo->client_tcpopt->wscale, (char*)header, &offset, &nr_tlvs);
tcp_restore_info_tlv_add(TCP_RESTORE_INFO_TLV_WSACLE_SERVER, 1, pmeinfo->server_tcpopt->wscale, (char*)header, &offset, &nr_tlvs);
tcp_restore_info_tlv_add(TCP_RESTORE_INFO_TLV_SACK_CLIENT, 1, pmeinfo->client_tcpopt->sack, (char*)header, &offset, &nr_tlvs);
tcp_restore_info_tlv_add(TCP_RESTORE_INFO_TLV_SACK_SERVER, 1, pmeinfo->server_tcpopt->sack, (char*)header, &offset, &nr_tlvs);
tcp_restore_info_tlv_add(TCP_RESTORE_INFO_TLV_TS_CLIENT, 1, pmeinfo->client_tcpopt->ts, (char*)header, &offset, &nr_tlvs);
tcp_restore_info_tlv_add(TCP_RESTORE_INFO_TLV_TS_SERVER, 1, pmeinfo->server_tcpopt->ts, (char*)header, &offset, &nr_tlvs);
header->__magic__[0] = 0x4d;
header->__magic__[1] = 0x5a;
header->nr_tlvs = htons(nr_tlvs);
*len = offset;
return header;
}
static char* tcp_restore_info_header_add(struct pme_info *pmeinfo, struct pkt_info *pktinfo, int *len){
//tcp option: kind 88, len 4, control_info_len
char *new_pkt = (char*)ALLOC(struct wrapped_packet, 1);
struct iphdr *iphdr = (struct iphdr*)new_pkt;
int offset = 0;
//iphdr
memcpy(new_pkt, (void*)pktinfo->iphdr, pktinfo->iphdr_len);
offset += pktinfo->iphdr_len;
//tcphdr
struct tcphdr *tcphdr = (struct tcphdr*)(new_pkt + offset);
memcpy(new_pkt + offset, (void*)pktinfo->tcphdr, 20);
offset += 20;
tcphdr->doff = pktinfo->tcphdr->doff + 1;
struct tcp_option_restore *opt = ALLOC(struct tcp_option_restore, 1);
opt->kind = 88;
opt->len = 4;
opt->offset = htons(pktinfo->data_len);
memcpy(new_pkt + offset, (void*)opt, 4);
offset += 4;
memcpy(new_pkt + offset, (void*)((char*)pktinfo->tcphdr + 20), pktinfo->tcphdr_len - 20);
offset += pktinfo->tcphdr_len - 20;
//data
memcpy(new_pkt + offset, (void*)pktinfo->data, pktinfo->data_len);
offset += pktinfo->data_len;
//tcp_restore_info_header
int header_len = 0;
struct tcp_restore_info_header* header = tcp_restore_info_header_new(pmeinfo, pktinfo, &header_len);
memcpy(new_pkt + offset, (void*)header, header_len);
offset += header_len;
free(header);
//iphdr: tot_len
iphdr->tot_len = htons(offset);
//iphdr: checksum
//计算校验和之前一定要先置0
iphdr->check = 0;
iphdr->check = kni_ip_checksum((void*)iphdr, pktinfo->iphdr_len);
//tcphdr: checkdum
tcphdr->check = 0;
tcphdr->check = kni_tcp_checksum((void*)tcphdr, offset - pktinfo->iphdr_len, iphdr->saddr, iphdr->daddr);
*len = offset;
return new_pkt;
}
static int send_to_tfe(struct kni_marsio_handle *handle, char *raw_data, int raw_len, int thread_seq){
void *logger = g_kni_handle->logger;
KNI_LOG_DEBUG(logger, "send packet to tfe");
marsio_buff_t *tx_buffs[BURST_MAX];
unsigned int ret = 1;
//TODO: marsio配置文件: 2500
int alloc_ret = marsio_buff_malloc_device(handle->dev_handler, tx_buffs, ret, 0, thread_seq);
if (alloc_ret < 0){
KNI_LOG_ERROR(logger, "Failed at alloc marsio buffer, ret is %d, thread_seq is %d", ret, thread_seq);
return -1;
}
void * dst_data = marsio_buff_append(tx_buffs[0], raw_len + 14);
unsigned char ethernet_header[14] = {0xfe, 0x65, 0xb7, 0x03, 0x50, 0xbd, 0xe8, 0x61, 0x1f, 0x13, 0x70, 0x7a, 0x08, 0x00};
memcpy(dst_data, ethernet_header, 14);
memcpy((char*)dst_data + 14, raw_data, raw_len);
marsio_send_burst(handle->dev_sendpath, thread_seq, tx_buffs, ret);
return 0;
}
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;
}
static int get_action(struct ipaddr *addr, char *domain, int domain_len, int thread_seq){
//return KNI_ACTION_INTERCEPT;
int action = kni_maat_scan_ip(g_kni_handle->maat_handle, addr, thread_seq, g_kni_handle->logger);
if(action == KNI_ACTION_BYPASS){
return action;
}
action = kni_maat_scan_domain(g_kni_handle->maat_handle, domain, domain_len, thread_seq, g_kni_handle->logger);
return action;
}
//TODO: 这一块逻辑需要和洋姐和秋秋讨论一下
static char data_opstate(const struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo, int thread_seq){
void *logger = g_kni_handle->logger;
char *buf = (char*)pktinfo->iphdr;
int len = pktinfo->ip_totlen;
//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
//此时 action = KNI_ACTION_UNKNOWN, 说明还没收到第一个数据包
// 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);
protocol_identify(stream, pktinfo->data, pktinfo->data_len, result);
pmeinfo->protocol = result->protocol;
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");
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;
//pktinfo
struct pkt_info *pktinfo = (struct pkt_info*)ALLOC(struct pkt_info, 1);
pktinfo->iphdr = (struct iphdr*)a_packet;
pktinfo->iphdr_len = pktinfo->iphdr->ihl * 4;
pktinfo->ip_totlen = ntohs(pktinfo->iphdr->tot_len);
pktinfo->tcphdr = (struct tcphdr*)((char*)pktinfo->iphdr + pktinfo->iphdr_len);
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;
switch(stream->pktstate){
case OP_STATE_PENDING:
*pme = pmeinfo = pme_info_new();
ret = pending_opstate(stream, pmeinfo, pktinfo);
break;
case OP_STATE_DATA:
ret = data_opstate(stream, pmeinfo, pktinfo, thread_seq);
break;
case OP_STATE_CLOSE:
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);
if((ret & APP_STATE_DROPME)){
pme_info_destroy(pmeinfo);
*pme = NULL;
}
return ret;
}
void http_project_free(int thread_seq, void *project_req_value){
FREE(&project_req_value);
}
static int http_project_init(){
void *logger = g_kni_handle->logger;
int id = project_producer_register(HTTP_PROJECT_NAME, PROJECT_VAL_TYPE_STRUCT, http_project_free);
if(id < 0){
KNI_LOG_ERROR(logger, "Failed at project_producer_register, project name is %s, ret is %d", HTTP_PROJECT_NAME, id);
return -1;
}
id = project_customer_register(HTTP_PROJECT_NAME, PROJECT_VAL_TYPE_STRUCT);
if(id < 0){
KNI_LOG_ERROR(logger, "Failed at project_customer_register, project name is %s, ret is %d", HTTP_PROJECT_NAME, id);
return -1;
}
return id;
}
extern "C" char kni_http_entry(stSessionInfo* session_info, void **pme, int thread_seq, struct streaminfo *a_stream, const void *a_packet){
http_infor* http_info = (http_infor*)(session_info->app_info);
//http_session_seq = 1表示只处理tcp链接中的第一个http会话
if(http_info->http_session_seq != 1){
return PROT_STATE_DROPME;
}
if(session_info->prot_flag != HTTP_HOST){
return PROT_STATE_GIVEME;
}
int host_len = MIN(session_info->buflen, KNI_DEFAULT_MTU);
struct http_project* host_info = ALLOC(struct http_project, 1);
host_info->host_len = host_len;
memcpy(host_info->host, session_info->buf, host_len);
if(project_req_add_struct(a_stream, g_kni_handle->http_project_id, host_info) < 0){
FREE(&host_info);
host_info = NULL;
}
return PROT_STATE_DROPME;
}
static void kni_marsio_destroy(struct kni_marsio_handle *handle){
//TODO: dev_handler, dev_sendpath不需要free吗
if(handle != NULL){
if(handle->instance != NULL){
marsio_destory(handle->instance);
}
}
FREE(&handle);
}
static struct kni_marsio_handle* kni_marsio_init(const char* profile){
void *logger = g_kni_handle->logger;
const char* section = "marsio";
char appsym[KNI_SYMBOL_MAX];
char dev_symbol[KNI_SYMBOL_MAX];
MESA_load_profile_string_def(profile, section, "appsym", appsym, sizeof(appsym), "unknown");
MESA_load_profile_string_def(profile, section, "dev_symbol", dev_symbol, sizeof(dev_symbol), "unknown");
KNI_LOG_INFO(logger, "MESA_prof_load, [%s]:\n appsym: %s\n dev_symbol: %s", section, appsym, dev_symbol);
struct mr_instance *instance = marsio_create();
if(instance == NULL){
KNI_LOG_ERROR(logger, "Failed at marsio_create");
return NULL;
}
unsigned int opt_value = 1;
marsio_option_set(instance, MARSIO_OPT_EXIT_WHEN_ERR, &opt_value, sizeof(opt_value));
//uint64_t cpu_mask = 0x3c; //??
//marsio_option_set(handle->instance, MARSIO_OPT_THREAD_MASK, &cpu_mask, sizeof(cpu_mask));
marsio_init(instance, appsym);
//设为sapp线程数
int nr_thread = g_iThreadNum;
struct mr_vdev * dev_handler = marsio_open_device(instance, dev_symbol, nr_thread, nr_thread);
if(dev_handler == NULL){
KNI_LOG_ERROR(logger, "Failed at marsio_open_device, dev_symbol is %s, nr_thread is %d", dev_symbol, nr_thread);
return NULL;
}
struct mr_sendpath * dev_sendpath = marsio_sendpath_create_by_vdev(dev_handler);
if(dev_sendpath == NULL){
KNI_LOG_ERROR(logger, "Failed at marsio_sendpath_create_by_vdev");
return NULL;
}
struct kni_marsio_handle *handle = ALLOC(struct kni_marsio_handle, 1);
handle->instance = instance;
handle->dev_handler = dev_handler;
handle->dev_sendpath = dev_sendpath;
//暂时不用调
//marsio_thread_init(mr_instance);
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";
const char *section = "global";
//init logger
char log_path[KNI_PATH_MAX];
MESA_load_profile_string_def(profile, section, "log_path", log_path, sizeof(log_path), "unknown");
int log_level;
MESA_load_profile_int_def(profile, section, "log_level", &log_level, 10);
void *logger = MESA_create_runtime_log_handle(log_path, log_level);
if (unlikely(logger == NULL))
{
printf("Failed at create logger: %s, exit", log_path);
exit(EXIT_FAILURE);
}
KNI_LOG_INFO(logger, "MESA_prof_load, [%s]:\n log_path: %s\n log_level: %d", section, log_path, log_level);
g_kni_handle->logger = logger;
//init http_project
int id = http_project_init();
if(id < 0){
KNI_LOG_ERROR(logger, "Failed at init http project, exit. ret is %d", id);
exit(EXIT_FAILURE);
}
g_kni_handle->http_project_id = id;
//init marsio
g_kni_handle->marsio_handle = kni_marsio_init(profile);
if(g_kni_handle->marsio_handle == NULL){
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 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;
}