增加ipv6支持

This commit is contained in:
崔一鸣
2019-06-14 11:13:15 +08:00
parent 3ed1bac877
commit 02abbae3d9
5 changed files with 546 additions and 225 deletions

View File

@@ -6,7 +6,6 @@
#include <pthread.h> #include <pthread.h>
#include <unistd.h> #include <unistd.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/tcp.h>
#include <time.h> #include <time.h>
#include "MESA/MESA_handle_logger.h" #include "MESA/MESA_handle_logger.h"
#include "MESA/MESA_htable.h" #include "MESA/MESA_htable.h"
@@ -92,6 +91,10 @@ enum kni_field{
KNI_FIELD_ID2PME_ADD_FAIL, KNI_FIELD_ID2PME_ADD_FAIL,
KNI_FIELD_ID2PME_DEL_SUCC, KNI_FIELD_ID2PME_DEL_SUCC,
KNI_FIELD_ID2PME_DEL_FAIL, KNI_FIELD_ID2PME_DEL_FAIL,
KNI_FIELD_IPV4HDR_PARSE_FAIL,
KNI_FIELD_IPV6HDR_PARSE_FAIL,
KNI_FIELD_KEEPALIVE_REPLAY_ADD_SUCC,
KNI_FIELD_KEEPALIVE_REPLAY_ADD_FAIL,
}; };
struct kni_field_stat_handle{ struct kni_field_stat_handle{
@@ -99,12 +102,40 @@ struct kni_field_stat_handle{
int fields[KNI_FIELD_MAX]; int fields[KNI_FIELD_MAX];
}; };
int kni_stream_addr_trans(const struct layer_addr *addr, char *output, int len); struct pkt_info{
union{
struct iphdr *v4;
struct ip6_hdr *v6;
}iphdr;
uint16_t iphdr_len;
uint16_t ip_totlen;
struct tcphdr *tcphdr;
uint16_t tcphdr_len;
char *data;
uint16_t data_len;
};
enum kni_ipv4hdr_parse_error{
KNI_IPV4HDR_PARSE_ERROR_NULL_PACKET = -1,
};
enum kni_ipv6hdr_parse_error{
KNI_IPV6HDR_PARSE_ERROR_NULL_PACKET = -1,
KNI_IPV6HDR_PARSE_ERROR_NO_TCPHDR = -2,
KNI_IPV6HDR_PARSE_ERROR_INVALID_TYPE = -3,
};
int kni_stream_addr_trans(const struct layer_addr *addr, addr_type_t addr_type, char *output, int len);
uint16_t kni_ip_checksum(const void *buf, size_t hdr_len); 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_tcp_checksum(const void *_buf, size_t len, in_addr_t src_addr, in_addr_t dest_addr);
uint16_t kni_tcp_checksum_v6(const void *_buf, size_t len, struct in6_addr src_addr, struct in6_addr dest_addr);
uint16_t kni_udp_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);
struct kni_tcpopt_info* kni_get_tcpopt(struct tcphdr* tcphdr,int tcphdr_len); struct kni_tcpopt_info* kni_get_tcpopt(struct tcphdr* tcphdr, int tcphdr_len);
int kni_ipv4_addr_get_by_eth(const char *ifname, uint32_t *ip); int kni_ipv4_addr_get_by_eth(const char *ifname, uint32_t *ip);
int kni_ipv4_header_parse(const void *a_packet, struct pkt_info *pktinfo);
int kni_ipv6_header_parse(const void *a_packet, struct pkt_info *pktinfo);
char* kni_ipv4_errmsg_get(enum kni_ipv4hdr_parse_error _errno);
char* kni_ipv6_errmsg_get(enum kni_ipv6hdr_parse_error _errno);
MESA_htable_handle kni_create_htable(const char *profile, const char *section, void *free_data_cb, void *expire_notify_cb, void *logger); MESA_htable_handle kni_create_htable(const char *profile, const char *section, void *free_data_cb, void *expire_notify_cb, void *logger);

View File

@@ -1,13 +1,25 @@
#include "kni_utils.h" #include "kni_utils.h"
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <netinet/ip6.h>
#include <net/if.h> #include <net/if.h>
int kni_stream_addr_trans(const struct layer_addr *addr, char *output, int len){ int kni_stream_addr_trans(const struct layer_addr *addr, addr_type_t addr_type, char *output, int len){
char saddr[INET_ADDRSTRLEN]; char saddr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET, &(addr->tuple4_v4->saddr), saddr, INET_ADDRSTRLEN); char daddr[INET6_ADDRSTRLEN];
char daddr[INET_ADDRSTRLEN]; uint16_t source, dest;
inet_ntop(AF_INET, &(addr->tuple4_v4->daddr), daddr, INET_ADDRSTRLEN); if(addr_type == ADDR_TYPE_IPV6){
snprintf(output, len, "%s:%d -> %s:%d", saddr, ntohs(addr->tuple4_v4->source), daddr, ntohs(addr->tuple4_v4->dest)); inet_ntop(AF_INET6, &(addr->tuple4_v6->saddr), saddr, INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &(addr->tuple4_v6->daddr), daddr, INET6_ADDRSTRLEN);
source = ntohs(addr->tuple4_v6->source);
dest = ntohs(addr->tuple4_v6->dest);
}
else{
inet_ntop(AF_INET, &(addr->tuple4_v4->saddr), saddr, INET6_ADDRSTRLEN);
inet_ntop(AF_INET, &(addr->tuple4_v4->daddr), daddr, INET6_ADDRSTRLEN);
source = ntohs(addr->tuple4_v4->source);
dest = ntohs(addr->tuple4_v4->dest);
}
snprintf(output, len, "%s:%d -> %s:%d", saddr, source, daddr, dest);
return 0; return 0;
} }
@@ -28,6 +40,43 @@ uint16_t kni_ip_checksum(const void *buf, size_t hdr_len){
return (~sum); return (~sum);
} }
uint16_t kni_tcp_checksum_v6(const void *_buf, size_t len, struct in6_addr src_addr, struct in6_addr dest_addr){
const uint16_t *buf = (u_int16_t *)_buf;
uint16_t *ip_src=(uint16_t *)&src_addr, *ip_dst=(uint16_t *)&dest_addr;
uint32_t sum;
size_t length=len;
// Calculate the sum
sum = 0;
while(len > 1){
sum += *buf++;
if (sum & 0x80000000){
sum = (sum & 0xFFFF) + (sum >> 16);
}
len -= 2;
}
if(len & 1){
// Add the padding if the packet lenght is odd
sum += *((uint8_t *)buf);
}
// Add the pseudo-header
for(int i = 0; i < 8; i++){
sum += *ip_src;
ip_src++;
}
for(int i = 0; i < 8; i++){
sum += *ip_dst;
ip_dst++;
}
sum += htons(IPPROTO_TCP);
sum += htons(length);
// Add the carries
while(sum >> 16){
sum = (sum & 0xFFFF) + (sum >> 16);
}
// Return the one's complement of sum
return ((uint16_t)(~sum));
}
uint16_t kni_tcp_checksum(const void *_buf, size_t len, in_addr_t src_addr, in_addr_t dest_addr){ uint16_t kni_tcp_checksum(const void *_buf, size_t len, in_addr_t src_addr, in_addr_t dest_addr){
const uint16_t *buf = (u_int16_t *)_buf; const uint16_t *buf = (u_int16_t *)_buf;
uint16_t *ip_src=(uint16_t *)&src_addr, *ip_dst=(uint16_t *)&dest_addr; uint16_t *ip_src=(uint16_t *)&src_addr, *ip_dst=(uint16_t *)&dest_addr;
@@ -255,4 +304,82 @@ MESA_htable_handle kni_create_htable(const char *profile, const char *section, v
return NULL; return NULL;
} }
return htable; return htable;
}
char* kni_ipv4_errmsg_get(int _errno){
switch(_errno){
case KNI_IPV4HDR_PARSE_ERROR_NULL_PACKET:
return (char*)"null packet";
default:
return (char*)"unknown error";
}
}
char* kni_ipv6_errmsg_get(int _errno){
switch(_errno){
case KNI_IPV6HDR_PARSE_ERROR_NULL_PACKET:
return (char*)"null packet";
case KNI_IPV6HDR_PARSE_ERROR_NO_TCPHDR:
return (char*)"no tcp header";
case KNI_IPV6HDR_PARSE_ERROR_INVALID_TYPE:
return (char*)"invalid header type";
default:
return (char*)"unknown error";
}
}
int kni_ipv4_header_parse(const void *a_packet, struct pkt_info *pktinfo){
if(a_packet == NULL){
return KNI_IPV4HDR_PARSE_ERROR_NULL_PACKET;
}
pktinfo->iphdr.v4 = (struct iphdr*)a_packet;
pktinfo->iphdr_len = pktinfo->iphdr.v4->ihl * 4;
pktinfo->ip_totlen = ntohs(pktinfo->iphdr.v4->tot_len);
pktinfo->tcphdr = (struct tcphdr*)((char*)pktinfo->iphdr.v4 + 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;
return 0;
}
int kni_ipv6_header_parse(const void *a_packet, struct pkt_info *pktinfo){
if(a_packet == NULL){
return KNI_IPV6HDR_PARSE_ERROR_NULL_PACKET;
}
pktinfo->iphdr.v6 = (struct ip6_hdr*)a_packet;
pktinfo->ip_totlen = ntohs(pktinfo->iphdr.v6->ip6_ctlun.ip6_un1.ip6_un1_plen) + sizeof(struct ip6_hdr);
uint8_t next_hdr_type = pktinfo->iphdr.v6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
char *next_hdr_ptr = (char*)pktinfo->iphdr.v6 + sizeof(struct ip6_hdr);
int skip_len = 0;
int ret = 0;
while(true){
switch(next_hdr_type)
{
case IPPROTO_TCP:
//parse tcphdr
pktinfo->iphdr_len = next_hdr_ptr - (char*)a_packet;
pktinfo->tcphdr = (struct tcphdr*)next_hdr_ptr;
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;
return 0;
case IPPROTO_HOPOPTS:
case IPPROTO_ROUTING:
case IPPROTO_AH:
case IPPROTO_DSTOPTS:
skip_len = (*(next_hdr_ptr + 1)) * 8 + 8;
next_hdr_type = *next_hdr_ptr;
next_hdr_ptr += skip_len;
break;
case IPPROTO_NONE:
ret = KNI_IPV6HDR_PARSE_ERROR_NO_TCPHDR;
goto error_out;
default:
ret = KNI_IPV6HDR_PARSE_ERROR_INVALID_TYPE;
goto error_out;
}
}
error_out:
return ret;
} }

View File

@@ -28,4 +28,4 @@ enum kni_action{
struct kni_maat_handle* kni_maat_init(const char* profile, void *logger); struct kni_maat_handle* kni_maat_init(const char* profile, void *logger);
void kni_maat_destroy(struct kni_maat_handle *handle); void kni_maat_destroy(struct kni_maat_handle *handle);
enum kni_action intercept_policy_scan(struct kni_maat_handle* handle, struct ipaddr *addr, char *domain, int domain_len, int thread_seq, int *policy_id, int *is_hit_policy); enum kni_action intercept_policy_scan(struct kni_maat_handle* handle, struct ipaddr *addr, char *domain, int domain_len, int thread_seq, int *policy_id, int *is_hit_policy);
int kni_maat_action_trans(enum kni_action action, char *action_str); char* kni_maat_action_trans(enum kni_action action);

View File

@@ -18,7 +18,7 @@ struct kni_field_stat_handle *g_kni_fs_handle = NULL;
#define HTTP_PROJECT_NAME "kni_http_tag" #define HTTP_PROJECT_NAME "kni_http_tag"
#define BURST_MAX 1 #define BURST_MAX 1
#define stream_traceid_LEN 37 #define STREAM_TRACEID_LEN 37
#define TFE_COUNT_MAX 16 #define TFE_COUNT_MAX 16
#define CALLER_SAPP 0 #define CALLER_SAPP 0
#define CALLER_TFE 1 #define CALLER_TFE 1
@@ -37,6 +37,9 @@ enum stream_error{
STREAM_ERROR_NO_SYN_ACK = -4, STREAM_ERROR_NO_SYN_ACK = -4,
STREAM_ERROR_INVALID_ACTION = -5, STREAM_ERROR_INVALID_ACTION = -5,
STREAM_ERROR_NO_DATA = -6, STREAM_ERROR_NO_DATA = -6,
STREAM_ERROR_IPV4HDR_PARSE_FAIL = -7,
STREAM_ERROR_IPV6HDR_PARSE_FAIL = -8,
STREAM_ERROR_DUP_STREAM = -9,
}; };
struct http_project{ struct http_project{
@@ -45,6 +48,7 @@ struct http_project{
}; };
struct pme_info{ struct pme_info{
addr_type_t addr_type;
int protocol; int protocol;
int policy_id; int policy_id;
int maat_hit; int maat_hit;
@@ -57,12 +61,12 @@ struct pme_info{
int tfe_id; int tfe_id;
pthread_mutex_t lock; pthread_mutex_t lock;
enum stream_error error; enum stream_error error;
char stream_traceid[stream_traceid_LEN]; char stream_traceid[STREAM_TRACEID_LEN];
//cjson check protocol //cjson check protocol
union{ union{
char host[KNI_DOMAIN_MAX]; //http only char host[KNI_DOMAIN_MAX]; //http only
char sni[KNI_DOMAIN_MAX]; //ssl only char sni[KNI_DOMAIN_MAX]; //ssl only
}; }domain;
//tfe_release = 1: tfe don't need pmeinfo //tfe_release = 1: tfe don't need pmeinfo
int tfe_release; int tfe_release;
int sapp_release; int sapp_release;
@@ -130,16 +134,6 @@ struct thread_tfe_cmsg_receiver_args{
char profile[KNI_SYMBOL_MAX]; char profile[KNI_SYMBOL_MAX];
}; };
struct pkt_info{
struct iphdr *iphdr;
int iphdr_len;
int ip_totlen;
struct tcphdr *tcphdr;
int tcphdr_len;
char *data;
int data_len;
};
struct kni_handle{ struct kni_handle{
int http_project_id; int http_project_id;
struct kni_marsio_handle *marsio_handle; struct kni_marsio_handle *marsio_handle;
@@ -167,11 +161,35 @@ struct keepalive_replay_htable_value{
struct keepalive_replay_search_cb_args{ struct keepalive_replay_search_cb_args{
marsio_buff_t *rx_buff; marsio_buff_t *rx_buff;
struct kni_marsio_handle *marsio_handle; struct kni_marsio_handle *marsio_handle;
struct iphdr *raw_packet_iphdr; void *raw_packet;
addr_type_t addr_type;
int tfe_id; int tfe_id;
int thread_seq; int thread_seq;
}; };
static char* stream_errmsg_get(enum stream_error _errno){
switch(_errno){
case STREAM_ERROR_PENDING_NO_SYN:
return (char*)"penging not syn";
case STREAM_ERROR_SINGLE_DIR:
return (char*)"single dir";
case STREAM_ERROR_PROTOCOL_UNKNOWN:
return (char*)"protocol unknown";
case STREAM_ERROR_NO_SYN_ACK:
return (char*)"no syn/ack";
case STREAM_ERROR_INVALID_ACTION:
return (char*)"invalid aciton";
case STREAM_ERROR_NO_DATA:
return (char*)"";
case STREAM_ERROR_IPV4HDR_PARSE_FAIL:
return (char*)"ipv4 header parse fail";
case STREAM_ERROR_IPV6HDR_PARSE_FAIL:
return (char*)"ipv6 header parse fail";
default:
return (char*)"unknown error";
}
}
static void pme_info_destroy(void *data){ static void pme_info_destroy(void *data){
struct pme_info *pmeinfo = (struct pme_info *)data; struct pme_info *pmeinfo = (struct pme_info *)data;
void *logger = g_kni_handle->local_logger; void *logger = g_kni_handle->local_logger;
@@ -200,6 +218,7 @@ static void pme_info_destroy(void *data){
static struct pme_info* pme_info_new(const struct streaminfo *stream, int thread_seq){ static struct pme_info* pme_info_new(const struct streaminfo *stream, int thread_seq){
void *logger = g_kni_handle->local_logger; void *logger = g_kni_handle->local_logger;
struct pme_info* pmeinfo = ALLOC(struct pme_info, 1); struct pme_info* pmeinfo = ALLOC(struct pme_info, 1);
pmeinfo->addr_type = (enum addr_type_t)stream->addr.addrtype;
pmeinfo->tfe_id = g_kni_handle->tfe_count > 0 ? thread_seq % g_kni_handle->tfe_count : -1; pmeinfo->tfe_id = g_kni_handle->tfe_count > 0 ? thread_seq % g_kni_handle->tfe_count : -1;
uuid_t uu; uuid_t uu;
uuid_generate_random(uu); uuid_generate_random(uu);
@@ -213,7 +232,7 @@ static struct pme_info* pme_info_new(const struct streaminfo *stream, int thread
KNI_LOG_ERROR(logger, "Failed at init pthread mutex, stream_traceid is %s", pmeinfo->stream_traceid); KNI_LOG_ERROR(logger, "Failed at init pthread mutex, stream_traceid is %s", pmeinfo->stream_traceid);
goto error_out; goto error_out;
} }
kni_stream_addr_trans(&(stream->addr), stream_addr, sizeof(stream_addr)); kni_stream_addr_trans(&(stream->addr), pmeinfo->addr_type, stream_addr, sizeof(stream_addr));
KNI_LOG_INFO(logger, "stream addr is %s, stream traceid is %s", stream_addr, pmeinfo->stream_traceid); KNI_LOG_INFO(logger, "stream addr is %s, stream traceid is %s", stream_addr, pmeinfo->stream_traceid);
//FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_TOT_STM], 0, FS_OP_ADD, 1); //FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_TOT_STM], 0, FS_OP_ADD, 1);
return pmeinfo; return pmeinfo;
@@ -307,11 +326,11 @@ static int sendlog_to_kafka(struct pme_info *pmeinfo, void *local_logger){
cJSON_AddStringToObject(log_obj, "addr_list", ""); cJSON_AddStringToObject(log_obj, "addr_list", "");
//host: http_only //host: http_only
if(pmeinfo->protocol == KNI_PROTOCOL_HTTP){ if(pmeinfo->protocol == KNI_PROTOCOL_HTTP){
cJSON_AddStringToObject(log_obj, "host", pmeinfo->host); cJSON_AddStringToObject(log_obj, "host", pmeinfo->domain.host);
} }
//sni: ssl only //sni: ssl only
if(pmeinfo->protocol == KNI_PROTOCOL_SSL){ if(pmeinfo->protocol == KNI_PROTOCOL_SSL){
cJSON_AddStringToObject(log_obj, "sni", pmeinfo->sni); cJSON_AddStringToObject(log_obj, "sni", pmeinfo->domain.sni);
} }
//c2s_pkt_num //c2s_pkt_num
cJSON_AddNumberToObject(log_obj, "c2s_pkt_num", pmeinfo->server_pkts); cJSON_AddNumberToObject(log_obj, "c2s_pkt_num", pmeinfo->server_pkts);
@@ -389,11 +408,21 @@ static void judge_pme_destroy(struct pme_info *pmeinfo, int caller){
} }
//del keepalive_replay_htable //del keepalive_replay_htable
char stream_addr[KNI_SYMBOL_MAX] = ""; char stream_addr[KNI_SYMBOL_MAX] = "";
kni_stream_addr_trans((const layer_addr*)(pmeinfo->addr), stream_addr, sizeof(stream_addr)); kni_stream_addr_trans((const layer_addr*)(pmeinfo->addr), pmeinfo->addr_type, stream_addr, sizeof(stream_addr));
//c2s //c2s
struct stream_tuple4_v4 *c2s_key = pmeinfo->addr->tuple4_v4; struct stream_tuple4_v4 *c2s_key_v4 = NULL;
key_size = sizeof(*c2s_key); struct stream_tuple4_v6 *c2s_key_v6 = NULL;
ret = MESA_htable_del(g_kni_handle->keepalive_replay_htable, (const unsigned char*)c2s_key, key_size, NULL); key_size = 0;
if(pmeinfo->addr_type == ADDR_TYPE_IPV6){
c2s_key_v6 = pmeinfo->addr->tuple4_v6;
key_size = sizeof(struct stream_tuple4_v6);
ret = MESA_htable_del(g_kni_handle->keepalive_replay_htable, (const unsigned char*)c2s_key_v6, key_size, NULL);
}
else{
c2s_key_v4 = pmeinfo->addr->tuple4_v4;
key_size = sizeof(struct stream_tuple4_v4);
ret = MESA_htable_del(g_kni_handle->keepalive_replay_htable, (const unsigned char*)c2s_key_v4, key_size, NULL);
}
if(ret < 0){ if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_htable: Failed at del, table is %s, stream addr is %s, dir is c2s, ret is %d", KNI_LOG_ERROR(logger, "MESA_htable: Failed at del, table is %s, stream addr is %s, dir is c2s, ret is %d",
"keepalive_replay_htable", stream_addr, ret); "keepalive_replay_htable", stream_addr, ret);
@@ -403,13 +432,26 @@ static void judge_pme_destroy(struct pme_info *pmeinfo, int caller){
"keepalive_replay_htable", stream_addr); "keepalive_replay_htable", stream_addr);
} }
//s2c //s2c
struct stream_tuple4_v4 s2c_key; if(pmeinfo->addr_type == ADDR_TYPE_IPV6){
key_size = sizeof(s2c_key); struct stream_tuple4_v6 s2c_key_v6;
s2c_key.saddr = c2s_key->daddr; memcpy(s2c_key_v6.saddr, c2s_key_v6->daddr, sizeof(s2c_key_v6.saddr));
s2c_key.daddr = c2s_key->saddr; memcpy(s2c_key_v6.daddr, c2s_key_v6->saddr, sizeof(s2c_key_v6.daddr));
s2c_key.source = c2s_key->dest; s2c_key_v6.source = c2s_key_v6->dest;
s2c_key.dest = c2s_key->source; s2c_key_v6.dest = c2s_key_v6->source;
ret = MESA_htable_del(g_kni_handle->keepalive_replay_htable, (const unsigned char*)&s2c_key, key_size, NULL); key_size = sizeof(struct stream_tuple4_v6);
ret = MESA_htable_del(g_kni_handle->keepalive_replay_htable, (const unsigned char*)&s2c_key_v6,
key_size, NULL);
}
else{
struct stream_tuple4_v4 s2c_key_v4;
s2c_key_v4.saddr = c2s_key_v4->daddr;
s2c_key_v4.daddr = c2s_key_v4->saddr;
s2c_key_v4.source = c2s_key_v4->dest;
s2c_key_v4.dest = c2s_key_v4->source;
key_size = sizeof(struct stream_tuple4_v4);
ret = MESA_htable_del(g_kni_handle->keepalive_replay_htable, (const unsigned char*)&s2c_key_v4,
key_size, NULL);
}
if(ret < 0){ if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_htable: Failed at del, table is %s, stream addr is %s, dir is s2c, ret is %d", KNI_LOG_ERROR(logger, "MESA_htable: Failed at del, table is %s, stream addr is %s, dir is s2c, ret is %d",
"keepalive_replay_htable", stream_addr, ret); "keepalive_replay_htable", stream_addr, ret);
@@ -462,6 +504,7 @@ static int protocol_identify(const struct streaminfo* stream, char *buf, int len
result->protocol = KNI_PROTOCOL_UNKNOWN; result->protocol = KNI_PROTOCOL_UNKNOWN;
return 0; return 0;
} }
static int wrapped_kni_cmsg_set(struct kni_cmsg *cmsg, uint16_t type, const unsigned char *value, static int wrapped_kni_cmsg_set(struct kni_cmsg *cmsg, uint16_t type, const unsigned char *value,
uint16_t size, char *stream_traceid){ uint16_t size, char *stream_traceid){
void *logger = g_kni_handle->local_logger; void *logger = g_kni_handle->local_logger;
@@ -556,10 +599,14 @@ error_out:
static char* add_cmsg_to_packet(struct pme_info *pmeinfo, struct pkt_info *pktinfo, int *len){ static char* add_cmsg_to_packet(struct pme_info *pmeinfo, struct pkt_info *pktinfo, int *len){
//tcp option: kind 88, len 4, control_info_len //tcp option: kind 88, len 4, control_info_len
char *new_pkt = (char*)ALLOC(struct wrapped_packet, 1); char *new_pkt = (char*)ALLOC(struct wrapped_packet, 1);
struct iphdr *iphdr = (struct iphdr*)new_pkt;
int offset = 0; int offset = 0;
//iphdr //iphdr
memcpy(new_pkt, (void*)pktinfo->iphdr, pktinfo->iphdr_len); if(pmeinfo->addr_type == ADDR_TYPE_IPV6){
memcpy(new_pkt, (void*)pktinfo->iphdr.v6, pktinfo->iphdr_len);
}
else{
memcpy(new_pkt, (void*)pktinfo->iphdr.v4, pktinfo->iphdr_len);
}
offset += pktinfo->iphdr_len; offset += pktinfo->iphdr_len;
//tcphdr //tcphdr
struct tcphdr *tcphdr = (struct tcphdr*)(new_pkt + offset); struct tcphdr *tcphdr = (struct tcphdr*)(new_pkt + offset);
@@ -583,19 +630,29 @@ static char* add_cmsg_to_packet(struct pme_info *pmeinfo, struct pkt_info *pktin
memcpy(new_pkt + offset, (void*)header, header_len); memcpy(new_pkt + offset, (void*)header, header_len);
offset += header_len; offset += header_len;
FREE(&header); FREE(&header);
//iphdr: tot_len //ipv6
iphdr->tot_len = htons(offset); if(pmeinfo->addr_type == ADDR_TYPE_IPV6){
//must set check = 0 kni_ipv6_header_parse((void*)new_pkt, pktinfo);
iphdr->check = 0; pktinfo->iphdr.v6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(offset - sizeof(ip6_hdr));
iphdr->check = kni_ip_checksum((void*)iphdr, pktinfo->iphdr_len); pktinfo->tcphdr->check = 0;
//tcphdr: checkdum pktinfo->tcphdr->check = kni_tcp_checksum_v6((void*)pktinfo->tcphdr,
tcphdr->check = 0; offset - pktinfo->iphdr_len, pktinfo->iphdr.v6->ip6_src, pktinfo->iphdr.v6->ip6_dst);
tcphdr->check = kni_tcp_checksum((void*)tcphdr, offset - pktinfo->iphdr_len, iphdr->saddr, iphdr->daddr); }
else{
struct iphdr *iphdr = (struct iphdr*)new_pkt;
iphdr->tot_len = htons(offset);
//must set check = 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; *len = offset;
return new_pkt; return new_pkt;
} }
static int send_to_tfe(struct kni_marsio_handle *handle, char *raw_data, int raw_len, int thread_seq, int tfe_id){ static int send_to_tfe(struct kni_marsio_handle *handle, char *raw_data, uint16_t raw_len, int thread_seq, int tfe_id){
void *logger = g_kni_handle->local_logger; void *logger = g_kni_handle->local_logger;
marsio_buff_t *tx_buffs[BURST_MAX]; marsio_buff_t *tx_buffs[BURST_MAX];
struct mr_vdev *dev_eth_handler = handle->tfe_instance_list[tfe_id]->dev_eth_handler; struct mr_vdev *dev_eth_handler = handle->tfe_instance_list[tfe_id]->dev_eth_handler;
@@ -623,24 +680,146 @@ static int send_to_tfe(struct kni_marsio_handle *handle, char *raw_data, int raw
return 0; return 0;
} }
static char pending_opstate(const struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo){ static int wrapped_kni_header_parse(const void *a_packet, struct pme_info *pmeinfo, struct pkt_info *pktinfo){
void *logger = g_kni_handle->local_logger; void *logger = g_kni_handle->local_logger;
if(!pktinfo->tcphdr->syn){ if(pmeinfo->addr_type == ADDR_TYPE_IPV6){
int ret = kni_ipv6_header_parse(a_packet, pktinfo);
if(ret < 0){
char *errmsg = kni_ipv6_errmsg_get((enum kni_ipv6hdr_parse_error)ret);
KNI_LOG_ERROR(logger, "Failed at parse ipv6 header, bypass and dropme, errmsg is %s, stream treaceid is %s",
errmsg, pmeinfo->stream_traceid);
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_IPV6HDR_PARSE_FAIL], 0, FS_OP_ADD, 1);
pmeinfo->error = STREAM_ERROR_IPV6HDR_PARSE_FAIL;
return -1;
}
}
else{
int ret = kni_ipv4_header_parse(a_packet, pktinfo);
if(ret < 0){
char *errmsg = kni_ipv4_errmsg_get((enum kni_ipv4hdr_parse_error)ret);
KNI_LOG_ERROR(logger, "Failed at parse ipv4 header, bypass and dropme, errmsg is %s, stream treaceid is %s",
errmsg, pmeinfo->stream_traceid);
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_IPV4HDR_PARSE_FAIL], 0, FS_OP_ADD, 1);
pmeinfo->error = STREAM_ERROR_IPV4HDR_PARSE_FAIL;
return -1;
}
}
return 0;
}
static char pending_opstate(const struct streaminfo *stream, struct pme_info *pmeinfo, const void *a_packet){
void *logger = g_kni_handle->local_logger;
struct pkt_info pktinfo;
int ret = wrapped_kni_header_parse(a_packet, pmeinfo, &pktinfo);
if(ret < 0){
return APP_STATE_FAWPKT | APP_STATE_DROPME;
}
if(!pktinfo.tcphdr->syn){
//pending_opstate not syn, bypass and dropme //pending_opstate not syn, bypass and dropme
KNI_LOG_DEBUG(logger, "pending opstate: not syn, stream traceid is %s", pmeinfo->stream_traceid); KNI_LOG_DEBUG(logger, "pending opstate: not syn, stream traceid is %s", pmeinfo->stream_traceid);
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_NO_SYN_EXP], 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_BYP_PKT], 0, FS_OP_ADD, 1);
pmeinfo->error = STREAM_ERROR_PENDING_NO_SYN; pmeinfo->error = STREAM_ERROR_PENDING_NO_SYN;
return APP_STATE_FAWPKT | APP_STATE_DROPME; return APP_STATE_FAWPKT | APP_STATE_DROPME;
} }
pmeinfo->client_window = pktinfo->tcphdr->window; pmeinfo->client_window = pktinfo.tcphdr->window;
pmeinfo->client_tcpopt = kni_get_tcpopt(pktinfo->tcphdr, pktinfo->tcphdr_len); 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; return APP_STATE_FAWPKT | APP_STATE_GIVEME;
} }
static char data_opstate(const struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo, int thread_seq){ static int first_data_intercept(const struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo, char *stream_addr, int thread_seq){
void *logger = g_kni_handle->local_logger;
struct keepalive_replay_htable_value *c2s_value = ALLOC(struct keepalive_replay_htable_value, 1);
c2s_value->first_data_len = pktinfo->data_len;
int key_size = 0, ret;
struct stream_tuple4_v4 *c2s_key_v4 = NULL;
struct stream_tuple4_v6 *c2s_key_v6 = NULL;
if(pmeinfo->addr_type == ADDR_TYPE_IPV6){
c2s_key_v6 = stream->addr.tuple4_v6;
key_size = sizeof(*c2s_key_v6);
ret = MESA_htable_add(g_kni_handle->keepalive_replay_htable, (const unsigned char *)c2s_key_v6, key_size, (const void*)c2s_value);
}
else{
c2s_key_v4 = stream->addr.tuple4_v4;
key_size = sizeof(*c2s_key_v4);
ret = MESA_htable_add(g_kni_handle->keepalive_replay_htable, (const unsigned char *)c2s_key_v4, key_size, (const void*)c2s_value);
}
if(ret < 0){
//tfe not release, sapp release but not expire, so the same stream can not add, bypass and dropme
if(ret != MESA_HTABLE_RET_DUP_ITEM){
KNI_LOG_ERROR(logger, "MESA_htable: Failed at add, table is keepalive_replay_htable, "
"dir is c2s, key is %s, key_size is %d, ret is %d", stream_addr, key_size, ret);
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_KEEPALIVE_REPLAY_ADD_FAIL], 0, FS_OP_ADD, 1);
}
pmeinfo->error = STREAM_ERROR_DUP_STREAM;
return APP_STATE_FAWPKT | APP_STATE_DROPME;
}
else{
KNI_LOG_DEBUG(logger, "MESA_htable: Succeed at add, table is keepalive_replay_htable, "
"dir is c2s, key is %s, key_size is %d", stream_addr, key_size);
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_KEEPALIVE_REPLAY_ADD_SUCC], 0, FS_OP_ADD, 1);
}
//s2c
struct keepalive_replay_htable_value *s2c_value = ALLOC(struct keepalive_replay_htable_value, 1);
if(pmeinfo->addr_type == ADDR_TYPE_IPV6){
struct stream_tuple4_v6 s2c_key_v6;
key_size = sizeof(s2c_key_v6);
memcpy(s2c_key_v6.saddr, c2s_key_v6->daddr, sizeof(s2c_key_v6.saddr));
memcpy(s2c_key_v6.daddr, c2s_key_v6->saddr, sizeof(s2c_key_v6.daddr));
s2c_key_v6.source = c2s_key_v6->dest;
s2c_key_v6.dest = c2s_key_v6->source;
ret = MESA_htable_add(g_kni_handle->keepalive_replay_htable, (const unsigned char *)(&s2c_key_v6),
key_size, (const void*)s2c_value);
}
else{
struct stream_tuple4_v4 s2c_key_v4;
key_size = sizeof(s2c_key_v4);
s2c_key_v4.saddr = c2s_key_v4->daddr;
s2c_key_v4.daddr = c2s_key_v4->saddr;
s2c_key_v4.source = c2s_key_v4->dest;
s2c_key_v4.dest = c2s_key_v4->source;
ret = MESA_htable_add(g_kni_handle->keepalive_replay_htable, (const unsigned char *)(&s2c_key_v4),
key_size, (const void*)s2c_value);
}
if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_htable: Failed at add, table is keepalive_replay_htable, "
"dir is s2c, key is %s, key_size is %d, ret is %d", stream_addr, key_size, ret);
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_KEEPALIVE_REPLAY_ADD_FAIL], 0, FS_OP_ADD, 1);
}
else{
KNI_LOG_DEBUG(logger, "MESA_htable: Succeed at add, table is keepalive_replay_htable, "
"dir is s2c, key is %s, key_size is %d", stream_addr, key_size);
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_KEEPALIVE_REPLAY_ADD_SUCC], 0, FS_OP_ADD, 1);
}
//only intercept: add to traceid2pme htable
key_size = strnlen(pmeinfo->stream_traceid, sizeof(pmeinfo->stream_traceid));
ret = MESA_htable_add(g_kni_handle->traceid2pme_htable, (const unsigned char *)(pmeinfo->stream_traceid),
key_size, (const void*)pmeinfo);
if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_htable: Failed at add,"
"table is traceid2pme_htable, key is %s, ret is %d", pmeinfo->stream_traceid, ret);
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2PME_ADD_FAIL], 0, FS_OP_ADD, 1);
}
else{
KNI_LOG_DEBUG(logger, "MESA_htable: Succeed at add,"
"table is traceid2pme_htable, key is %s", pmeinfo->stream_traceid);
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2PME_ADD_SUCC], 0, FS_OP_ADD, 1);
}
//action = KNI_ACTION_INTERCEPT, sendto tfe
int len = 0;
char *buf = add_cmsg_to_packet(pmeinfo, pktinfo, &len);
ret = send_to_tfe(g_kni_handle->marsio_handle, buf, len, thread_seq, pmeinfo->tfe_id);
if(ret < 0){
KNI_LOG_ERROR(logger, "Failed at send first packet to tfe%d, stream traceid is %s", pmeinfo->tfe_id, pmeinfo->stream_traceid);
}
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 data_opstate(const struct streaminfo *stream, struct pme_info *pmeinfo, const void *a_packet, int thread_seq){
//pmeinfo->tfe_release = 1: intercept, tfe end first. so droppkt and dropme //pmeinfo->tfe_release = 1: intercept, tfe end first. so droppkt and dropme
if(pmeinfo->tfe_release == 1){ if(pmeinfo->tfe_release == 1){
pmeinfo->server_bytes=stream->ptcpdetail->serverbytes; pmeinfo->server_bytes=stream->ptcpdetail->serverbytes;
@@ -651,17 +830,25 @@ static char data_opstate(const struct streaminfo *stream, struct pme_info *pmein
return APP_STATE_DROPPKT | APP_STATE_DROPME; return APP_STATE_DROPPKT | APP_STATE_DROPME;
} }
void *logger = g_kni_handle->local_logger; void *logger = g_kni_handle->local_logger;
char *buf = (char*)pktinfo->iphdr; struct iphdr *ipv4_hdr = NULL;
int len = pktinfo->ip_totlen; struct ip6_hdr *ipv6_hdr = NULL;
int ret; uint16_t len = 0, ret;
char stream_addr[KNI_SYMBOL_MAX] = ""; char stream_addr[KNI_SYMBOL_MAX] = "";
kni_stream_addr_trans(&(stream->addr), stream_addr, sizeof(stream_addr)); kni_stream_addr_trans(&(stream->addr), pmeinfo->addr_type, stream_addr, sizeof(stream_addr));
//pmeinfo->action has only 3 value: KNI_ACTION_NONE KNI_ACTION_INTERCEPT KNI_ACTION_BYPASS //pmeinfo->action has only 3 value: KNI_ACTION_NONE KNI_ACTION_INTERCEPT KNI_ACTION_BYPASS
switch (pmeinfo->action){ switch (pmeinfo->action){
case KNI_ACTION_NONE: case KNI_ACTION_NONE:
break; break;
case KNI_ACTION_INTERCEPT: case KNI_ACTION_INTERCEPT:
ret = send_to_tfe(g_kni_handle->marsio_handle, buf, len, thread_seq, pmeinfo->tfe_id); if(pmeinfo->addr_type == ADDR_TYPE_IPV6){
ipv6_hdr = (struct ip6_hdr*)a_packet;
len = ntohs(ipv6_hdr->ip6_ctlun.ip6_un1.ip6_un1_plen) + sizeof(struct ip6_hdr);
}
else{
ipv4_hdr = (struct iphdr*)a_packet;
len = ntohs(ipv4_hdr->tot_len);
}
ret = send_to_tfe(g_kni_handle->marsio_handle, (char*)a_packet, len, thread_seq, pmeinfo->tfe_id);
if(ret < 0){ if(ret < 0){
KNI_LOG_ERROR(logger, "Failed at send continue packet to tfe%d, stream traceid is %s", pmeinfo->tfe_id, pmeinfo->stream_traceid); KNI_LOG_ERROR(logger, "Failed at send continue packet to tfe%d, stream traceid is %s", pmeinfo->tfe_id, pmeinfo->stream_traceid);
} }
@@ -674,15 +861,21 @@ static char data_opstate(const struct streaminfo *stream, struct pme_info *pmein
assert(0); assert(0);
break; break;
} }
//parse ipv4/6 header
struct pkt_info pktinfo;
ret = wrapped_kni_header_parse(a_packet, pmeinfo, &pktinfo);
if(ret < 0){
return APP_STATE_FAWPKT | APP_STATE_DROPME;
}
// syn/ack // syn/ack
if(pktinfo->tcphdr->syn && pktinfo->tcphdr->ack){ if(pktinfo.tcphdr->syn && pktinfo.tcphdr->ack){
pmeinfo->server_window = pktinfo->tcphdr->window; pmeinfo->server_window = pktinfo.tcphdr->window;
pmeinfo->server_tcpopt = kni_get_tcpopt(pktinfo->tcphdr, pktinfo->tcphdr_len); 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); //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; return APP_STATE_FAWPKT | APP_STATE_GIVEME;
} }
//no data, maybe ack //no data, maybe ack
if(pktinfo->data_len <= 0){ 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); //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; return APP_STATE_FAWPKT | APP_STATE_GIVEME;
} }
@@ -696,7 +889,7 @@ static char data_opstate(const struct streaminfo *stream, struct pme_info *pmein
} }
struct protocol_identify_result protocol_identify_res; struct protocol_identify_result protocol_identify_res;
memset(&protocol_identify_res, 0, sizeof(protocol_identify_res)); memset(&protocol_identify_res, 0, sizeof(protocol_identify_res));
protocol_identify(stream, pktinfo->data, pktinfo->data_len, &protocol_identify_res); protocol_identify(stream, pktinfo.data, pktinfo.data_len, &protocol_identify_res);
pmeinfo->protocol = protocol_identify_res.protocol; pmeinfo->protocol = protocol_identify_res.protocol;
switch(pmeinfo->protocol){ switch(pmeinfo->protocol){
//can not identify protocol from first data packet, bypass and dropme //can not identify protocol from first data packet, bypass and dropme
@@ -709,11 +902,11 @@ static char data_opstate(const struct streaminfo *stream, struct pme_info *pmein
pmeinfo->error = STREAM_ERROR_PROTOCOL_UNKNOWN; pmeinfo->error = STREAM_ERROR_PROTOCOL_UNKNOWN;
return APP_STATE_FAWPKT | APP_STATE_DROPME; return APP_STATE_FAWPKT | APP_STATE_DROPME;
case KNI_PROTOCOL_SSL: case KNI_PROTOCOL_SSL:
strncpy(pmeinfo->sni, protocol_identify_res.domain, strnlen(protocol_identify_res.domain, sizeof(pmeinfo->sni) - 1)); strncpy(pmeinfo->domain.sni, protocol_identify_res.domain, strnlen(protocol_identify_res.domain, sizeof(pmeinfo->domain.sni) - 1));
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_SSL_STM], 0, FS_OP_ADD, 1); FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_SSL_STM], 0, FS_OP_ADD, 1);
break; break;
case KNI_PROTOCOL_HTTP: case KNI_PROTOCOL_HTTP:
strncpy(pmeinfo->host, protocol_identify_res.domain, strnlen(protocol_identify_res.domain, sizeof(pmeinfo->host) - 1)); strncpy(pmeinfo->domain.host, protocol_identify_res.domain, strnlen(protocol_identify_res.domain, sizeof(pmeinfo->domain.host) - 1));
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_HTTP_STM], 0, FS_OP_ADD, 1); FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_HTTP_STM], 0, FS_OP_ADD, 1);
break; break;
default: default:
@@ -723,106 +916,36 @@ static char data_opstate(const struct streaminfo *stream, struct pme_info *pmein
protocol_identify_res.domain, protocol_identify_res.domain_len, protocol_identify_res.domain, protocol_identify_res.domain_len,
thread_seq, &(pmeinfo->policy_id), &(pmeinfo->maat_hit)); thread_seq, &(pmeinfo->policy_id), &(pmeinfo->maat_hit));
//policy scan log //policy scan log
char action_str[KNI_SYMBOL_MAX]; char *action_str = kni_maat_action_trans(pmeinfo->action);
kni_maat_action_trans(pmeinfo->action, action_str);
KNI_LOG_DEBUG(logger, "intercept_policy_scan: %s, %s, policy_id = %d, action = %d(%s), maat_hit = %d", KNI_LOG_DEBUG(logger, "intercept_policy_scan: %s, %s, policy_id = %d, action = %d(%s), maat_hit = %d",
stream_addr, protocol_identify_res.domain, pmeinfo->policy_id, pmeinfo->action, action_str, pmeinfo->maat_hit); stream_addr, protocol_identify_res.domain, pmeinfo->policy_id, pmeinfo->action, action_str, pmeinfo->maat_hit);
//receive client hello, but no syn/ack, bypass and dropme //receive client hello, but no syn/ack, bypass and dropme
if(pmeinfo->client_tcpopt == NULL || pmeinfo->server_tcpopt == NULL){ if(pmeinfo->client_tcpopt == NULL || pmeinfo->server_tcpopt == NULL){
KNI_LOG_ERROR(logger, "Failed at intercept, %s, %s, stream traceid is %s", pmeinfo->client_tcpopt == NULL ? "no syn" : "", KNI_LOG_ERROR(logger, "Failed at intercept, %s, %s, stream traceid is %s", pmeinfo->client_tcpopt == NULL ? "no syn" : "have syn",
pmeinfo->server_tcpopt == NULL ? "no syn/ack" : "", pmeinfo->stream_traceid); pmeinfo->server_tcpopt == NULL ? "no syn/ack" : "have syn/ack", pmeinfo->stream_traceid);
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_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_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_BYP_STM], 0, FS_OP_ADD, 1);
pmeinfo->error = STREAM_ERROR_NO_SYN_ACK; pmeinfo->error = STREAM_ERROR_NO_SYN_ACK;
return APP_STATE_FAWPKT | APP_STATE_DROPME; return APP_STATE_FAWPKT | APP_STATE_DROPME;
} }
int key_size;
struct stream_tuple4_v4 *c2s_key = NULL;
struct stream_tuple4_v4 s2c_key;
struct keepalive_replay_htable_value *c2s_value = NULL;
struct keepalive_replay_htable_value *s2c_value = NULL;
switch(pmeinfo->action){ switch(pmeinfo->action){
case KNI_ACTION_BYPASS: case 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_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_BYP_STM], 0, FS_OP_ADD, 1);
return APP_STATE_FAWPKT | APP_STATE_GIVEME; return APP_STATE_FAWPKT | APP_STATE_GIVEME;
case KNI_ACTION_INTERCEPT: case KNI_ACTION_INTERCEPT:
//only intercept: add to traceid2pme htable return first_data_intercept(stream, pmeinfo, &pktinfo, stream_addr, thread_seq);
key_size = strnlen(pmeinfo->stream_traceid, sizeof(pmeinfo->stream_traceid));
ret = MESA_htable_add(g_kni_handle->traceid2pme_htable, (const unsigned char *)(pmeinfo->stream_traceid),
key_size, (const void*)pmeinfo);
if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_htable: Failed at add,"
"table is traceid2pme_htable, key is %s, ret is %d", pmeinfo->stream_traceid, ret);
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2PME_ADD_FAIL], 0, FS_OP_ADD, 1);
}
else{
KNI_LOG_DEBUG(logger, "MESA_htable: Succeed at add,"
"table is traceid2pme_htable, key is %s", pmeinfo->stream_traceid);
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2PME_ADD_SUCC], 0, FS_OP_ADD, 1);
}
//interctp: add to keepalive_replay_htable
//c2s
c2s_key = stream->addr.tuple4_v4;
key_size = sizeof(*c2s_key);
c2s_value = ALLOC(struct keepalive_replay_htable_value, 1);
c2s_value->first_data_len = pktinfo->data_len;
ret = MESA_htable_add(g_kni_handle->keepalive_replay_htable, (const unsigned char *)c2s_key,
key_size, (const void*)c2s_value);
if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_htable: Failed at add,"
"table is keepalive_replay_htable, dir is c2s, stream is %s, ret is %d", stream_addr, ret);
//FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2PME_ADD_FAIL], 0, FS_OP_ADD, 1);
}
else{
KNI_LOG_DEBUG(logger, "MESA_htable: Succeed at add,"
"table is keepalive_replay_htable, dir is c2s, stream is %s", stream_addr);
//FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2PME_ADD_SUCC], 0, FS_OP_ADD, 1);
}
//s2c
key_size = sizeof(s2c_key);
s2c_key.saddr = c2s_key->daddr;
s2c_key.daddr = c2s_key->saddr;
s2c_key.source = c2s_key->dest;
s2c_key.dest = c2s_key->source;
s2c_value = ALLOC(struct keepalive_replay_htable_value, 1);
ret = MESA_htable_add(g_kni_handle->keepalive_replay_htable, (const unsigned char *)(&s2c_key),
key_size, (const void*)s2c_value);
if(ret < 0){
KNI_LOG_ERROR(logger, "MESA_htable: Failed at add,"
"table is keepalive_replay_htable, dir is s2c, stream is %s, ret is %d", stream_addr, ret);
//FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2PME_ADD_FAIL], 0, FS_OP_ADD, 1);
}
else{
KNI_LOG_DEBUG(logger, "MESA_htable: Succeed at add,"
"table is keepalive_replay_htable, dir is s2c, stream is %s", stream_addr);
//FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_ID2PME_ADD_SUCC], 0, FS_OP_ADD, 1);
}
//action = KNI_ACTION_INTERCEPT, sendto tfe
buf = add_cmsg_to_packet(pmeinfo, pktinfo, &len);
ret = send_to_tfe(g_kni_handle->marsio_handle, buf, len, thread_seq, pmeinfo->tfe_id);
if(ret < 0){
KNI_LOG_ERROR(logger, "Failed at send first packet to tfe%d, stream traceid is %s", pmeinfo->tfe_id, pmeinfo->stream_traceid);
}
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;
default: default:
//action != intercept && action != bypassbypass and dropme //action != intercept && action != bypassbypass and dropme
KNI_LOG_ERROR(logger, "Action %d(%s) is invalid, bypass(dropme): policy_id is %d, stream addr is %s, domain is ", KNI_LOG_ERROR(logger, "Action %d(%s) is invalid, bypass(dropme): policy_id is %d, stream addr is %s, domain is ",
pmeinfo->action, action_str, pmeinfo->policy_id, stream_addr, protocol_identify_res.domain); pmeinfo->action, action_str, pmeinfo->policy_id, stream_addr, protocol_identify_res.domain);
//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);
pmeinfo->error = STREAM_ERROR_INVALID_ACTION; pmeinfo->error = STREAM_ERROR_INVALID_ACTION;
return APP_STATE_FAWPKT | APP_STATE_DROPME; return APP_STATE_FAWPKT | APP_STATE_DROPME;
} }
} }
static char close_opstate(const struct streaminfo *stream, struct pme_info *pmeinfo, struct pkt_info *pktinfo, int thread_seq){ static char close_opstate(const struct streaminfo *stream, struct pme_info *pmeinfo, int thread_seq){
//close: a_packet = null, do not sendto tfe //close: a_packet = null, do not sendto tfe
clock_gettime(CLOCK_REALTIME, &(pmeinfo->end_time)); clock_gettime(CLOCK_REALTIME, &(pmeinfo->end_time));
void *logger = g_kni_handle->local_logger; void *logger = g_kni_handle->local_logger;
@@ -843,8 +966,7 @@ static char close_opstate(const struct streaminfo *stream, struct pme_info *pmei
return APP_STATE_FAWPKT | APP_STATE_DROPME; return APP_STATE_FAWPKT | APP_STATE_DROPME;
//stream has only syn, ack. not data. do not send to tfe //stream has only syn, ack. not data. do not send to tfe
default: default:
char action_str[KNI_SYMBOL_MAX]; char *action_str = kni_maat_action_trans(pmeinfo->action);
kni_maat_action_trans(pmeinfo->action, action_str);
pmeinfo->error = STREAM_ERROR_NO_DATA; pmeinfo->error = STREAM_ERROR_NO_DATA;
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_STM_NO_DATA], 0, FS_OP_ADD, 1); FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_STM_NO_DATA], 0, FS_OP_ADD, 1);
KNI_LOG_DEBUG(logger, "close_opstate: action %d(%s) is abnormal, stream_traceid is %s", KNI_LOG_DEBUG(logger, "close_opstate: action %d(%s) is abnormal, stream_traceid is %s",
@@ -857,37 +979,22 @@ static char close_opstate(const struct streaminfo *stream, struct pme_info *pmei
extern "C" char kni_tcpall_entry(const struct streaminfo *stream, void** pme, int thread_seq, const void* a_packet){ extern "C" char kni_tcpall_entry(const struct streaminfo *stream, void** pme, int thread_seq, const void* a_packet){
void *logger = g_kni_handle->local_logger; void *logger = g_kni_handle->local_logger;
//FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_TOT_PKT], 0, FS_OP_ADD, 1);
int ret; int ret;
struct pme_info *pmeinfo = *(struct pme_info **)pme; struct pme_info *pmeinfo = *(struct pme_info **)pme;
//pktinfo
struct pkt_info pktinfo;
memset(&pktinfo, 0, sizeof(pktinfo));
//TODO: ipv6 //TODO: ipv6
if(stream->addr.addrtype == ADDR_TYPE_IPV6){ 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_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;
return APP_STATE_FAWPKT | APP_STATE_DROPME;
} }
//a_packet == NULL && not op_state_close, continue /* a_packet == NULL && not op_state_close, continue
//close: a_packet may be null, if a_packet = null, do not send to tfe close: a_packet may be null, if a_packet = null, do not send to tfe
*/
if(a_packet == NULL && stream->pktstate != OP_STATE_CLOSE){ if(a_packet == NULL && stream->pktstate != OP_STATE_CLOSE){
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_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; return APP_STATE_FAWPKT | APP_STATE_GIVEME;
} }
if(a_packet != NULL){
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;
}
switch(stream->pktstate){ switch(stream->pktstate){
case OP_STATE_PENDING: case OP_STATE_PENDING:
*pme = pmeinfo = pme_info_new(stream, thread_seq); *pme = pmeinfo = pme_info_new(stream, thread_seq);
@@ -896,13 +1003,13 @@ extern "C" char kni_tcpall_entry(const struct streaminfo *stream, void** pme, in
return APP_STATE_FAWPKT | APP_STATE_DROPME; return APP_STATE_FAWPKT | APP_STATE_DROPME;
} }
FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_PME_NEW], 0, FS_OP_ADD, 1); FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_PME_NEW], 0, FS_OP_ADD, 1);
ret = pending_opstate(stream, pmeinfo, &pktinfo); ret = pending_opstate(stream, pmeinfo, a_packet);
if(pmeinfo->error < 0){ if(pmeinfo->error < 0){
goto error_out; goto error_out;
} }
break; break;
case OP_STATE_DATA: case OP_STATE_DATA:
ret = data_opstate(stream, pmeinfo, &pktinfo, thread_seq); ret = data_opstate(stream, pmeinfo, a_packet, thread_seq);
//exception stream, dropme and destroy pmeinfo //exception stream, dropme and destroy pmeinfo
if(pmeinfo->error < 0){ if(pmeinfo->error < 0){
goto error_out; goto error_out;
@@ -910,14 +1017,13 @@ extern "C" char kni_tcpall_entry(const struct streaminfo *stream, void** pme, in
break; break;
case OP_STATE_CLOSE: case OP_STATE_CLOSE:
//sapp stream close //sapp stream close
ret = close_opstate(stream, pmeinfo, &pktinfo, thread_seq); ret = close_opstate(stream, pmeinfo, thread_seq);
if(pmeinfo->error < 0){ if(pmeinfo->error < 0){
goto error_out; goto error_out;
} }
break; break;
default: default:
ret = APP_STATE_FAWPKT | APP_STATE_GIVEME; 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); 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 traceid is %s", stream->pktstate, pmeinfo->stream_traceid); KNI_LOG_ERROR(logger, "Unknown stream opstate %d, stream traceid is %s", stream->pktstate, pmeinfo->stream_traceid);
break; break;
@@ -930,7 +1036,8 @@ extern "C" char kni_tcpall_entry(const struct streaminfo *stream, void** pme, in
//error out: no hash, no sendlog, just destroy_pme //error out: no hash, no sendlog, just destroy_pme
error_out: error_out:
KNI_LOG_DEBUG(logger, "stream error = %d, ret is %d, stream traceid is %s", pmeinfo->error, ret, pmeinfo->stream_traceid); char *stream_errmsg = stream_errmsg_get(pmeinfo->error);
KNI_LOG_DEBUG(logger, "stream error is %s, bypass and dropme, stream traceid is %s", stream_errmsg, pmeinfo->stream_traceid);
if(pmeinfo != NULL){ if(pmeinfo != NULL){
pme_info_destroy(pmeinfo); pme_info_destroy(pmeinfo);
} }
@@ -989,7 +1096,6 @@ static void kni_marsio_destroy(struct kni_marsio_handle *handle){
handle = NULL; handle = NULL;
} }
static void sendto_vxlan(marsio_buff_t *rx_buff, struct mr_sendpath *dev_vxlan_sendpath, int thread_seq){ static void sendto_vxlan(marsio_buff_t *rx_buff, struct mr_sendpath *dev_vxlan_sendpath, int thread_seq){
//tag //tag
struct mr_tunnat_ctrlzone mr_ctrlzone; struct mr_tunnat_ctrlzone mr_ctrlzone;
@@ -1018,27 +1124,59 @@ static long keepalive_replay_search_cb(void *data, const uchar *key, uint size,
sendto_vxlan(rx_buff, marsio_handle->dev_vxlan_sendpath, thread_seq); sendto_vxlan(rx_buff, marsio_handle->dev_vxlan_sendpath, thread_seq);
return 0; return 0;
} }
//raw_packet: window update //a_packet: window update
struct iphdr *raw_packet_iphdr = args->raw_packet_iphdr; void *raw_packet = args->raw_packet;
int tot_len = ntohs(raw_packet_iphdr->tot_len); char *replay_packet = NULL;
int iphdr_len = raw_packet_iphdr->ihl * 4; uint16_t tot_len = 0;
struct tcphdr *raw_packet_tcphdr = (struct tcphdr*)((char*)raw_packet_iphdr + iphdr_len); //ipv6
//replay packet if(args->addr_type == ADDR_TYPE_IPV6){
char *replay_packet = ALLOC(char, tot_len);
memcpy(replay_packet, (void*)raw_packet_iphdr, tot_len); struct pkt_info raw_pktinfo;
struct iphdr *replay_packet_iphdr = (struct iphdr*)replay_packet; int ret = kni_ipv6_header_parse(raw_packet, &raw_pktinfo);
struct tcphdr *replay_packet_tcphdr = (struct tcphdr*)((char*)replay_packet_iphdr + iphdr_len); if(ret < 0){
replay_packet_iphdr->saddr = raw_packet_iphdr->daddr; char *errmsg = kni_ipv6_errmsg_get((enum kni_ipv6hdr_parse_error)ret);
replay_packet_iphdr->daddr = raw_packet_iphdr->saddr; KNI_LOG_ERROR(logger, "Failed at parse ipv6 header, send to vxlan, errmsg is %s", errmsg);
replay_packet_tcphdr->source = raw_packet_tcphdr->dest; sendto_vxlan(rx_buff, marsio_handle->dev_vxlan_sendpath, thread_seq);
replay_packet_tcphdr->dest = raw_packet_tcphdr->source; return 0;
replay_packet_tcphdr->seq = htonl(ntohl(raw_packet_tcphdr->ack_seq) + value->first_data_len); //seq = ack + first_data_len }
replay_packet_tcphdr->ack_seq = htonl(ntohl(raw_packet_tcphdr->seq) + 1); //ack = seq + 1 tot_len = raw_pktinfo.ip_totlen;
replay_packet_iphdr->check = 0; replay_packet = ALLOC(char, tot_len);
replay_packet_iphdr->check = kni_ip_checksum((void*)replay_packet_iphdr, iphdr_len); memcpy(replay_packet, raw_packet, tot_len);
replay_packet_tcphdr->check = 0; struct pkt_info replay_pktinfo;
replay_packet_tcphdr->check = kni_tcp_checksum((void*)replay_packet_tcphdr, tot_len - iphdr_len, kni_ipv6_header_parse(replay_packet, &replay_pktinfo);
replay_packet_iphdr->saddr, replay_packet_iphdr->daddr); replay_pktinfo.iphdr.v6->ip6_src = raw_pktinfo.iphdr.v6->ip6_dst;
replay_pktinfo.iphdr.v6->ip6_dst = raw_pktinfo.iphdr.v6->ip6_src;
replay_pktinfo.tcphdr->source = raw_pktinfo.tcphdr->dest;
replay_pktinfo.tcphdr->dest = raw_pktinfo.tcphdr->source;
replay_pktinfo.tcphdr->seq = htonl(ntohl(raw_pktinfo.tcphdr->ack_seq) + value->first_data_len);
replay_pktinfo.tcphdr->ack_seq = htonl(ntohl(raw_pktinfo.tcphdr->seq) + 1);
replay_pktinfo.tcphdr->check = 0;
replay_pktinfo.tcphdr->check = kni_tcp_checksum_v6((void*)replay_pktinfo.tcphdr,
tot_len - replay_pktinfo.iphdr_len, replay_pktinfo.iphdr.v6->ip6_src, replay_pktinfo.iphdr.v6->ip6_dst);
}
//ipv4
else{
struct iphdr *raw_packet_iphdr = (struct iphdr*)raw_packet;
tot_len = ntohs(raw_packet_iphdr->tot_len);
uint16_t iphdr_len = raw_packet_iphdr->ihl * 4;
struct tcphdr *raw_packet_tcphdr = (struct tcphdr*)((char*)raw_packet_iphdr + iphdr_len);
//replay packet
replay_packet = ALLOC(char, tot_len);
memcpy(replay_packet, raw_packet, tot_len);
struct iphdr *replay_packet_iphdr = (struct iphdr*)replay_packet;
struct tcphdr *replay_packet_tcphdr = (struct tcphdr*)((char*)replay_packet_iphdr + iphdr_len);
replay_packet_iphdr->saddr = raw_packet_iphdr->daddr;
replay_packet_iphdr->daddr = raw_packet_iphdr->saddr;
replay_packet_tcphdr->source = raw_packet_tcphdr->dest;
replay_packet_tcphdr->dest = raw_packet_tcphdr->source;
replay_packet_tcphdr->seq = htonl(ntohl(raw_packet_tcphdr->ack_seq) + value->first_data_len); //seq = ack + first_data_len
replay_packet_tcphdr->ack_seq = htonl(ntohl(raw_packet_tcphdr->seq) + 1); //ack = seq + 1
replay_packet_iphdr->check = 0;
replay_packet_iphdr->check = kni_ip_checksum((void*)replay_packet_iphdr, iphdr_len);
replay_packet_tcphdr->check = 0;
replay_packet_tcphdr->check = kni_tcp_checksum((void*)replay_packet_tcphdr, tot_len - iphdr_len,
replay_packet_iphdr->saddr, replay_packet_iphdr->daddr);
}
//send to tfe: thread_seq = g_iThreadNum //send to tfe: thread_seq = g_iThreadNum
int ret = send_to_tfe(marsio_handle, replay_packet, tot_len, g_iThreadNum + thread_seq, tfe_id); int ret = send_to_tfe(marsio_handle, replay_packet, tot_len, g_iThreadNum + thread_seq, tfe_id);
if(ret < 0){ if(ret < 0){
@@ -1051,6 +1189,7 @@ static long keepalive_replay_search_cb(void *data, const uchar *key, uint size,
} }
void* thread_tfe_data_receiver(void *args){ void* thread_tfe_data_receiver(void *args){
void *logger = g_kni_handle->local_logger;
struct thread_tfe_data_receiver_args *_args = (struct thread_tfe_data_receiver_args*)args; struct thread_tfe_data_receiver_args *_args = (struct thread_tfe_data_receiver_args*)args;
struct kni_marsio_handle *marsio_handle = _args->marsio_handle; struct kni_marsio_handle *marsio_handle = _args->marsio_handle;
int thread_seq = _args->thread_seq; int thread_seq = _args->thread_seq;
@@ -1069,26 +1208,52 @@ void* thread_tfe_data_receiver(void *args){
if(g_kni_handle->keepalive_replay_switch == 1){ if(g_kni_handle->keepalive_replay_switch == 1){
for(int i = 0; i < nr_recv; i++){ for(int i = 0; i < nr_recv; i++){
struct ethhdr *ether_hdr = (struct ethhdr*)marsio_buff_mtod(rx_buffs[i]); struct ethhdr *ether_hdr = (struct ethhdr*)marsio_buff_mtod(rx_buffs[i]);
if(ether_hdr->h_proto == htons(ETH_P_IP)){ if(ether_hdr->h_proto == htons(ETH_P_IP) || ether_hdr->h_proto == htons(ETH_P_IPV6)){
struct iphdr *iphdr = (struct iphdr*)((char*)ether_hdr + sizeof(*ether_hdr)); void *raw_packet = (char*)ether_hdr + sizeof(*ether_hdr);
int iphdr_len = iphdr->ihl * 4;
struct tcphdr *tcphdr = (struct tcphdr*)((char*)iphdr + iphdr_len);
struct stream_tuple4_v4 key;
key.saddr = iphdr->saddr;
key.daddr = iphdr->daddr;
key.source = tcphdr->source;
key.dest = tcphdr->dest;
int key_size = sizeof(key);
long cb_ret = -1; long cb_ret = -1;
keepalive_replay_search_cb_args cb_args; keepalive_replay_search_cb_args cb_args;
memset(&cb_args, 0, sizeof(cb_args)); memset(&cb_args, 0, sizeof(cb_args));
cb_args.rx_buff = rx_buffs[i]; cb_args.rx_buff = rx_buffs[i];
cb_args.marsio_handle = marsio_handle; cb_args.marsio_handle = marsio_handle;
cb_args.raw_packet_iphdr = iphdr;
cb_args.tfe_id = i; cb_args.tfe_id = i;
cb_args.thread_seq = thread_seq; cb_args.thread_seq = thread_seq;
MESA_htable_search_cb(g_kni_handle->keepalive_replay_htable, (const unsigned char *)(&key), //ipv4
key_size, keepalive_replay_search_cb, &cb_args, &cb_ret); if(ether_hdr->h_proto == htons(ETH_P_IP)){
struct iphdr *iphdr = (struct iphdr*)raw_packet;
uint16_t iphdr_len = iphdr->ihl * 4;
struct tcphdr *tcphdr = (struct tcphdr*)((char*)iphdr + iphdr_len);
struct stream_tuple4_v4 key;
key.saddr = iphdr->saddr;
key.daddr = iphdr->daddr;
key.source = tcphdr->source;
key.dest = tcphdr->dest;
cb_args.addr_type = ADDR_TYPE_IPV4;
cb_args.raw_packet = raw_packet;
MESA_htable_search_cb(g_kni_handle->keepalive_replay_htable, (const unsigned char *)(&key),
sizeof(key), keepalive_replay_search_cb, &cb_args, &cb_ret);
}
//ipv6
else{
void *a_packet = (char*)ether_hdr + sizeof(*ether_hdr);
struct pkt_info pktinfo;
int ret = kni_ipv6_header_parse(a_packet, &pktinfo);
if(ret < 0){
char *errmsg = kni_ipv6_errmsg_get((enum kni_ipv6hdr_parse_error)ret);
KNI_LOG_ERROR(logger, "Failed at parse ipv6 header, send to vxlan, errmsg is %s", errmsg);
sendto_vxlan(rx_buffs[i], marsio_handle->dev_vxlan_sendpath, thread_seq);
}
else{
struct stream_tuple4_v6 key;
memcpy(key.saddr, &(pktinfo.iphdr.v6->ip6_src), sizeof(*(key.saddr)));
memcpy(key.daddr, &(pktinfo.iphdr.v6->ip6_dst), sizeof(*(key.daddr)));
key.source = pktinfo.tcphdr->source;
key.dest = pktinfo.tcphdr->dest;
cb_args.addr_type = ADDR_TYPE_IPV6;
cb_args.raw_packet = raw_packet;
MESA_htable_search_cb(g_kni_handle->keepalive_replay_htable, (const unsigned char *)(&key),
sizeof(key), keepalive_replay_search_cb, &cb_args, &cb_ret);
}
}
} }
else{ else{
sendto_vxlan(rx_buffs[i], marsio_handle->dev_vxlan_sendpath, thread_seq); sendto_vxlan(rx_buffs[i], marsio_handle->dev_vxlan_sendpath, thread_seq);
@@ -1105,6 +1270,7 @@ void* thread_tfe_data_receiver(void *args){
return NULL; return NULL;
} }
static int wrapped_kni_cmsg_get(struct pme_info *pmeinfo, struct kni_cmsg *cmsg, uint16_t type, static int wrapped_kni_cmsg_get(struct pme_info *pmeinfo, struct kni_cmsg *cmsg, uint16_t type,
uint16_t value_size_max, void *logger){ uint16_t value_size_max, void *logger){
uint16_t value_size = 0; uint16_t value_size = 0;
@@ -1446,6 +1612,10 @@ static struct kni_field_stat_handle * fs_init(const char *profile){
fs_handle->fields[KNI_FIELD_ID2PME_ADD_FAIL] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "id2pme_add_fail"); fs_handle->fields[KNI_FIELD_ID2PME_ADD_FAIL] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "id2pme_add_fail");
fs_handle->fields[KNI_FIELD_ID2PME_DEL_SUCC] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "id2pme_del_succ"); fs_handle->fields[KNI_FIELD_ID2PME_DEL_SUCC] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "id2pme_del_succ");
fs_handle->fields[KNI_FIELD_ID2PME_DEL_FAIL] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "id2pme_del_fail"); fs_handle->fields[KNI_FIELD_ID2PME_DEL_FAIL] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "id2pme_del_fail");
fs_handle->fields[KNI_FIELD_IPV4HDR_PARSE_FAIL] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "ipv4hdr_parse_fail");
fs_handle->fields[KNI_FIELD_IPV6HDR_PARSE_FAIL] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "ipv6hdr_parse_fail");
fs_handle->fields[KNI_FIELD_KEEPALIVE_REPLAY_ADD_FAIL] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "kaReplay_add_fail");
fs_handle->fields[KNI_FIELD_KEEPALIVE_REPLAY_ADD_SUCC] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "kaReplay_add_succ");
fs_handle->handle = handle; fs_handle->handle = handle;
FS_start(handle); FS_start(handle);
return fs_handle; return fs_handle;
@@ -1479,6 +1649,7 @@ static void keepalive_replay_data_free_cb(void *data)
FREE(&data); FREE(&data);
} }
extern "C" int kni_init(){ extern "C" int kni_init(){
const char *profile = "./conf/kni/kni.conf"; const char *profile = "./conf/kni/kni.conf";
const char *section = "global"; const char *section = "global";

View File

@@ -32,7 +32,8 @@ void compile_ex_param_new(int idx, const struct Maat_rule_t* rule, const char* s
void *logger = argp; void *logger = argp;
KNI_LOG_INFO(logger, "call compile_ex_param_new"); KNI_LOG_INFO(logger, "call compile_ex_param_new");
if(rule->config_id == 0){ if(rule->config_id == 0){
g_maat_default_action = (enum kni_action)rule->action; unsigned char action = (unsigned char)rule->action;
g_maat_default_action = (enum kni_action)action;
} }
return; return;
} }
@@ -245,34 +246,25 @@ enum kni_action intercept_policy_scan(struct kni_maat_handle* handle, struct ipa
0x60: steer 0x60: steer
0x80: bypass 0x80: bypass
*/ */
int kni_maat_action_trans(enum kni_action action, char *action_str){ char* kni_maat_action_trans(enum kni_action action){
switch(action){ switch(action){
case 0x00: case 0x00:
strcpy(action_str, "none"); return (char*)"none";
break;
case 0x01: case 0x01:
strcpy(action_str, "monitor"); return (char*)"monitor";
break;
case 0x02: case 0x02:
strcpy(action_str, "intercept"); return (char*)"intercept";
break;
case 0x10: case 0x10:
strcpy(action_str, "reject"); return (char*)"reject";
break;
case 0x30: case 0x30:
strcpy(action_str, "manipulate"); return (char*)"manipulate";
break;
case 0x60: case 0x60:
strcpy(action_str, "steer"); return (char*)"steer";
break;
case 0x80: case 0x80:
strcpy(action_str, "bypass"); return (char*)"bypass";
break;
default: default:
strcpy(action_str, "unknown"); return (char*)"unknown";
break;
} }
return 0;
} }