2019-05-17 17:04:50 +08:00
|
|
|
|
#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流中有多个http,ssl会话的情况,只扫描第一个
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-05-18 12:41:31 +08:00
|
|
|
|
struct kni_handle *g_kni_handle = NULL;
|
|
|
|
|
|
struct kni_field_stat_handle *g_kni_fs_handle = NULL;
|
|
|
|
|
|
|
2019-05-17 17:04:50 +08:00
|
|
|
|
//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;
|
2019-05-18 12:41:31 +08:00
|
|
|
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_TOT_STM], 0, FS_OP_ADD, 1);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
if(!pktinfo->tcphdr->syn){
|
|
|
|
|
|
//TODO: pending_opstate 不是syn, bypass这个流
|
|
|
|
|
|
KNI_LOG_ERROR(logger, "pending opstate: not syn");
|
2019-05-18 12:41:31 +08:00
|
|
|
|
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);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
return APP_STATE_FAWPKT | APP_STATE_DROPME;
|
|
|
|
|
|
}
|
|
|
|
|
|
pmeinfo->client_tcpopt = kni_get_tcpopt(pktinfo->tcphdr, pktinfo->tcphdr_len);
|
2019-05-18 12:41:31 +08:00
|
|
|
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
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);
|
2019-05-18 12:41:31 +08:00
|
|
|
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_INTCP_PKT], 0, FS_OP_ADD, 1);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
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);
|
2019-05-18 12:41:31 +08:00
|
|
|
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
return APP_STATE_FAWPKT | APP_STATE_GIVEME;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(pktinfo->data_len <= 0){
|
2019-05-18 12:41:31 +08:00
|
|
|
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
return APP_STATE_FAWPKT | APP_STATE_GIVEME;
|
|
|
|
|
|
}
|
|
|
|
|
|
//第一个数据包: 如果从第一个数据包判断不出协议,直接返回,后续包也不要了
|
|
|
|
|
|
//单向流, 直接bypass
|
|
|
|
|
|
if(stream->dir != DIR_DOUBLE){
|
|
|
|
|
|
KNI_LOG_INFO(logger, "stream dir is %d, bypass", stream->dir);
|
2019-05-18 12:41:31 +08:00
|
|
|
|
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);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
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);
|
2019-05-18 12:41:31 +08:00
|
|
|
|
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);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
return APP_STATE_FAWPKT | APP_STATE_DROPME;
|
|
|
|
|
|
}
|
|
|
|
|
|
//protocol = KNI_PROTOCOL_SSL/KNI_PROTOCOL_HTTP, 判断action, action返回值: KNI_ACTION_INTERCEPT/KNI_ACTION_BYPASS
|
2019-05-18 12:41:31 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
2019-05-17 17:04:50 +08:00
|
|
|
|
pmeinfo->action = get_action((struct ipaddr*)(&stream->addr), result->domain, result->domain_len, thread_seq);
|
|
|
|
|
|
FREE(&result);
|
|
|
|
|
|
if(pmeinfo->action == KNI_ACTION_BYPASS){
|
2019-05-18 12:41:31 +08:00
|
|
|
|
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);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
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" : "");
|
2019-05-18 12:41:31 +08:00
|
|
|
|
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);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
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);
|
2019-05-18 12:41:31 +08:00
|
|
|
|
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);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
return APP_STATE_DROPPKT | APP_STATE_GIVEME;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static char close_opstate(){
|
2019-05-18 12:41:31 +08:00
|
|
|
|
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_BYP_PKT], 0, FS_OP_ADD, 1);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
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;
|
2019-05-18 12:41:31 +08:00
|
|
|
|
//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);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
//当前包bypass, 剩下包bypass
|
|
|
|
|
|
//TODO: ipv6暂时不处理, ipv6: 通过nexthdr链式寻找tcp头(IPPROTO_TCP)
|
|
|
|
|
|
if(stream->addr.addrtype == ADDR_TYPE_IPV6){
|
2019-05-18 12:41:31 +08:00
|
|
|
|
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);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
return APP_STATE_FAWPKT | APP_STATE_DROPME;
|
|
|
|
|
|
}
|
|
|
|
|
|
//a_packet == NULL, 不处理这个包
|
|
|
|
|
|
if(a_packet == NULL){
|
2019-05-18 12:41:31 +08:00
|
|
|
|
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);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
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;
|
2019-05-18 12:41:31 +08:00
|
|
|
|
int ret;
|
2019-05-17 17:04:50 +08:00
|
|
|
|
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:
|
2019-05-18 12:41:31 +08:00
|
|
|
|
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);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-05-18 12:41:31 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-05-17 17:04:50 +08:00
|
|
|
|
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){
|
2019-05-18 12:41:31 +08:00
|
|
|
|
KNI_LOG_ERROR(logger, "Failed at init http project, exit. ret is %d", id);
|
2019-05-17 17:04:50 +08:00
|
|
|
|
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){
|
2019-05-18 12:41:31 +08:00
|
|
|
|
KNI_LOG_ERROR(logger, "Failed at init marsio, exit");
|
2019-05-17 17:04:50 +08:00
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//init maat
|
|
|
|
|
|
g_kni_handle->maat_handle = kni_maat_init(profile, logger);
|
|
|
|
|
|
if(g_kni_handle->maat_handle == NULL){
|
2019-05-18 12:41:31 +08:00
|
|
|
|
KNI_LOG_ERROR(logger, "Failed at init maat, exit");
|
2019-05-17 17:04:50 +08:00
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
|
}
|
2019-05-18 12:41:31 +08:00
|
|
|
|
|
|
|
|
|
|
//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;
|
|
|
|
|
|
|
2019-05-17 17:04:50 +08:00
|
|
|
|
return 0;
|
|
|
|
|
|
}
|