diff --git a/common/include/kni_utils.h b/common/include/kni_utils.h index 0cc83ed..46f4b15 100644 --- a/common/include/kni_utils.h +++ b/common/include/kni_utils.h @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "MESA/MESA_handle_logger.h" #include "MESA/MESA_htable.h" @@ -92,6 +91,11 @@ enum kni_field{ KNI_FIELD_ID2PME_ADD_FAIL, KNI_FIELD_ID2PME_DEL_SUCC, 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, + KNI_FIELD_EXCEED_MTU, }; struct kni_field_stat_handle{ @@ -99,12 +103,40 @@ struct kni_field_stat_handle{ 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_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); -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_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); \ No newline at end of file diff --git a/common/src/kni_utils.cpp b/common/src/kni_utils.cpp index 365a7b2..a9f9f22 100644 --- a/common/src/kni_utils.cpp +++ b/common/src/kni_utils.cpp @@ -1,13 +1,25 @@ #include "kni_utils.h" #include +#include #include -int kni_stream_addr_trans(const struct layer_addr *addr, char *output, int len){ - char saddr[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &(addr->tuple4_v4->saddr), saddr, INET_ADDRSTRLEN); - char daddr[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &(addr->tuple4_v4->daddr), daddr, INET_ADDRSTRLEN); - snprintf(output, len, "%s:%d -> %s:%d", saddr, ntohs(addr->tuple4_v4->source), daddr, ntohs(addr->tuple4_v4->dest)); +int kni_stream_addr_trans(const struct layer_addr *addr, addr_type_t addr_type, char *output, int len){ + char saddr[INET6_ADDRSTRLEN]; + char daddr[INET6_ADDRSTRLEN]; + uint16_t source, dest; + if(addr_type == ADDR_TYPE_IPV6){ + 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; } @@ -28,6 +40,43 @@ uint16_t kni_ip_checksum(const void *buf, size_t hdr_len){ 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){ const uint16_t *buf = (u_int16_t *)_buf; 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 htable; +} + +char* kni_ipv4_errmsg_get(enum kni_ipv4hdr_parse_error _errno){ + switch(_errno){ + case KNI_IPV4HDR_PARSE_ERROR_NULL_PACKET: + return (char*)"null packet"; + default: + return (char*)"unknown error"; + } +} + +char* kni_ipv6_errmsg_get(enum kni_ipv6hdr_parse_error _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; } \ No newline at end of file diff --git a/entry/include/kni_maat.h b/entry/include/kni_maat.h index f2c2f8e..8096f81 100644 --- a/entry/include/kni_maat.h +++ b/entry/include/kni_maat.h @@ -28,4 +28,4 @@ enum kni_action{ struct kni_maat_handle* kni_maat_init(const char* profile, void *logger); 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); -int kni_maat_action_trans(enum kni_action action, char *action_str); +char* kni_maat_action_trans(enum kni_action action); diff --git a/entry/src/kni_entry.cpp b/entry/src/kni_entry.cpp index fea579c..b58b1b0 100644 --- a/entry/src/kni_entry.cpp +++ b/entry/src/kni_entry.cpp @@ -18,7 +18,7 @@ struct kni_field_stat_handle *g_kni_fs_handle = NULL; #define HTTP_PROJECT_NAME "kni_http_tag" #define BURST_MAX 1 -#define stream_traceid_LEN 37 +#define STREAM_TRACEID_LEN 37 #define TFE_COUNT_MAX 16 #define CALLER_SAPP 0 #define CALLER_TFE 1 @@ -37,6 +37,10 @@ enum stream_error{ STREAM_ERROR_NO_SYN_ACK = -4, STREAM_ERROR_INVALID_ACTION = -5, STREAM_ERROR_NO_DATA = -6, + STREAM_ERROR_IPV4HDR_PARSE_FAIL = -7, + STREAM_ERROR_IPV6HDR_PARSE_FAIL = -8, + STREAM_ERROR_DUP_STREAM = -9, + STREAM_ERROR_EXCEED_MTU = -10, }; struct http_project{ @@ -45,6 +49,7 @@ struct http_project{ }; struct pme_info{ + addr_type_t addr_type; int protocol; int policy_id; int maat_hit; @@ -57,12 +62,12 @@ struct pme_info{ int tfe_id; pthread_mutex_t lock; enum stream_error error; - char stream_traceid[stream_traceid_LEN]; + char stream_traceid[STREAM_TRACEID_LEN]; //cjson check protocol union{ char host[KNI_DOMAIN_MAX]; //http only char sni[KNI_DOMAIN_MAX]; //ssl only - }; + }domain; //tfe_release = 1: tfe don't need pmeinfo int tfe_release; int sapp_release; @@ -130,16 +135,6 @@ struct thread_tfe_cmsg_receiver_args{ 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{ int http_project_id; struct kni_marsio_handle *marsio_handle; @@ -167,11 +162,37 @@ struct keepalive_replay_htable_value{ struct keepalive_replay_search_cb_args{ marsio_buff_t *rx_buff; struct kni_marsio_handle *marsio_handle; - struct iphdr *raw_packet_iphdr; + void *raw_packet; + addr_type_t addr_type; int tfe_id; 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*)"no data"; + case STREAM_ERROR_IPV4HDR_PARSE_FAIL: + return (char*)"ipv4 header parse fail"; + case STREAM_ERROR_IPV6HDR_PARSE_FAIL: + return (char*)"ipv6 header parse fail"; + case STREAM_ERROR_EXCEED_MTU: + return (char*)"exceed mtu(1500)"; + default: + return (char*)"unknown error"; + } +} + static void pme_info_destroy(void *data){ struct pme_info *pmeinfo = (struct pme_info *)data; void *logger = g_kni_handle->local_logger; @@ -200,6 +221,7 @@ static void pme_info_destroy(void *data){ static struct pme_info* pme_info_new(const struct streaminfo *stream, int thread_seq){ void *logger = g_kni_handle->local_logger; 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; uuid_t uu; uuid_generate_random(uu); @@ -213,7 +235,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); 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); //FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_TOT_STM], 0, FS_OP_ADD, 1); return pmeinfo; @@ -307,11 +329,11 @@ static int sendlog_to_kafka(struct pme_info *pmeinfo, void *local_logger){ cJSON_AddStringToObject(log_obj, "addr_list", ""); //host: http_only if(pmeinfo->protocol == KNI_PROTOCOL_HTTP){ - cJSON_AddStringToObject(log_obj, "host", pmeinfo->host); + cJSON_AddStringToObject(log_obj, "host", pmeinfo->domain.host); } //sni: ssl only if(pmeinfo->protocol == KNI_PROTOCOL_SSL){ - cJSON_AddStringToObject(log_obj, "sni", pmeinfo->sni); + cJSON_AddStringToObject(log_obj, "sni", pmeinfo->domain.sni); } //c2s_pkt_num cJSON_AddNumberToObject(log_obj, "c2s_pkt_num", pmeinfo->server_pkts); @@ -389,11 +411,21 @@ static void judge_pme_destroy(struct pme_info *pmeinfo, int caller){ } //del keepalive_replay_htable 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 - struct stream_tuple4_v4 *c2s_key = pmeinfo->addr->tuple4_v4; - key_size = sizeof(*c2s_key); - ret = MESA_htable_del(g_kni_handle->keepalive_replay_htable, (const unsigned char*)c2s_key, key_size, NULL); + struct stream_tuple4_v4 *c2s_key_v4 = NULL; + struct stream_tuple4_v6 *c2s_key_v6 = 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){ 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); @@ -403,13 +435,26 @@ static void judge_pme_destroy(struct pme_info *pmeinfo, int caller){ "keepalive_replay_htable", stream_addr); } //s2c - struct stream_tuple4_v4 s2c_key; - 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; - ret = MESA_htable_del(g_kni_handle->keepalive_replay_htable, (const unsigned char*)&s2c_key, key_size, NULL); + if(pmeinfo->addr_type == ADDR_TYPE_IPV6){ + struct stream_tuple4_v6 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; + 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){ 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); @@ -462,6 +507,7 @@ static int protocol_identify(const struct streaminfo* stream, char *buf, int len result->protocol = KNI_PROTOCOL_UNKNOWN; return 0; } + static int wrapped_kni_cmsg_set(struct kni_cmsg *cmsg, uint16_t type, const unsigned char *value, uint16_t size, char *stream_traceid){ void *logger = g_kni_handle->local_logger; @@ -556,10 +602,14 @@ error_out: 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 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); + 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; //tcphdr struct tcphdr *tcphdr = (struct tcphdr*)(new_pkt + offset); @@ -583,19 +633,29 @@ static char* add_cmsg_to_packet(struct pme_info *pmeinfo, struct pkt_info *pktin memcpy(new_pkt + offset, (void*)header, header_len); offset += header_len; FREE(&header); - //iphdr: tot_len - 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); + //ipv6 + if(pmeinfo->addr_type == ADDR_TYPE_IPV6){ + kni_ipv6_header_parse((void*)new_pkt, pktinfo); + pktinfo->iphdr.v6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(offset - sizeof(ip6_hdr)); + pktinfo->tcphdr->check = 0; + pktinfo->tcphdr->check = kni_tcp_checksum_v6((void*)pktinfo->tcphdr, + offset - pktinfo->iphdr_len, pktinfo->iphdr.v6->ip6_src, pktinfo->iphdr.v6->ip6_dst); + } + 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; 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, addr_type_t addr_type){ void *logger = g_kni_handle->local_logger; marsio_buff_t *tx_buffs[BURST_MAX]; struct mr_vdev *dev_eth_handler = handle->tfe_instance_list[tfe_id]->dev_eth_handler; @@ -616,31 +676,161 @@ static int send_to_tfe(struct kni_marsio_handle *handle, char *raw_data, int raw struct ethhdr *ether_hdr = (struct ethhdr*)dst_data; memcpy(ether_hdr->h_dest, dst_mac, sizeof(ether_hdr->h_dest)); memcpy(ether_hdr->h_source, src_mac, sizeof(ether_hdr->h_source)); - ether_hdr->h_proto = htons(ETH_P_IP); + if(addr_type == ADDR_TYPE_IPV6){ + ether_hdr->h_proto = htons(ETH_P_IPV6); + } + else{ + ether_hdr->h_proto = htons(ETH_P_IP); + } memcpy((char*)dst_data + sizeof(*ether_hdr), raw_data, raw_len); } marsio_send_burst(dev_eth_sendpath, thread_seq, tx_buffs, nr_send); 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; - 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 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_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; return APP_STATE_FAWPKT | APP_STATE_DROPME; } - pmeinfo->client_window = pktinfo->tcphdr->window; - 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); + pmeinfo->client_window = pktinfo.tcphdr->window; + pmeinfo->client_tcpopt = kni_get_tcpopt(pktinfo.tcphdr, pktinfo.tcphdr_len); 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, pmeinfo->addr_type); + 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); + } + else{ + KNI_LOG_DEBUG(logger, "Succeed 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 if(pmeinfo->tfe_release == 1){ pmeinfo->server_bytes=stream->ptcpdetail->serverbytes; @@ -651,17 +841,25 @@ static char data_opstate(const struct streaminfo *stream, struct pme_info *pmein return APP_STATE_DROPPKT | APP_STATE_DROPME; } void *logger = g_kni_handle->local_logger; - char *buf = (char*)pktinfo->iphdr; - int len = pktinfo->ip_totlen; - int ret; + struct iphdr *ipv4_hdr = NULL; + struct ip6_hdr *ipv6_hdr = NULL; + uint16_t len = 0, ret; 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 switch (pmeinfo->action){ case KNI_ACTION_NONE: break; 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, pmeinfo->addr_type); 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); } @@ -674,46 +872,53 @@ static char data_opstate(const struct streaminfo *stream, struct pme_info *pmein assert(0); 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; + } + //first data > 1500, bypass and dropme + if(pktinfo.ip_totlen > KNI_DEFAULT_MTU){ + pmeinfo->error = STREAM_ERROR_EXCEED_MTU; + KNI_LOG_ERROR(logger, "first data packet exceed MTU(1500), bypass and dropme"); + FS_operate(g_kni_fs_handle->handle, g_kni_fs_handle->fields[KNI_FIELD_EXCEED_MTU], 0, FS_OP_ADD, 1); + return APP_STATE_FAWPKT | APP_STATE_DROPME; + } // syn/ack - if(pktinfo->tcphdr->syn && pktinfo->tcphdr->ack){ - pmeinfo->server_window = pktinfo->tcphdr->window; - 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); + if(pktinfo.tcphdr->syn && pktinfo.tcphdr->ack){ + pmeinfo->server_window = pktinfo.tcphdr->window; + pmeinfo->server_tcpopt = kni_get_tcpopt(pktinfo.tcphdr, pktinfo.tcphdr_len); return APP_STATE_FAWPKT | APP_STATE_GIVEME; } //no data, maybe ack - 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); + if(pktinfo.data_len <= 0){ return APP_STATE_FAWPKT | APP_STATE_GIVEME; } //not double dir, bypass and dropme if(stream->dir != DIR_DOUBLE){ KNI_LOG_INFO(logger, "dir is %d, bypass, stream addr is %s", stream->dir, stream_addr); - //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_SINGLE_DIR; return APP_STATE_FAWPKT | APP_STATE_DROPME; } struct protocol_identify_result 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; switch(pmeinfo->protocol){ //can not identify protocol from first data packet, bypass and dropme case KNI_PROTOCOL_UNKNOWN: KNI_LOG_INFO(logger, "Failed at protocol_identify, bypass and dropme, stream addr is %s\n", pmeinfo->protocol, stream_addr); - //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); pmeinfo->error = STREAM_ERROR_PROTOCOL_UNKNOWN; return APP_STATE_FAWPKT | APP_STATE_DROPME; 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); break; 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); break; default: @@ -723,106 +928,34 @@ static char data_opstate(const struct streaminfo *stream, struct pme_info *pmein protocol_identify_res.domain, protocol_identify_res.domain_len, thread_seq, &(pmeinfo->policy_id), &(pmeinfo->maat_hit)); //policy scan log - char action_str[KNI_SYMBOL_MAX]; - 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", - stream_addr, protocol_identify_res.domain, pmeinfo->policy_id, pmeinfo->action, action_str, pmeinfo->maat_hit); + char *action_str = kni_maat_action_trans(pmeinfo->action); + KNI_LOG_DEBUG(logger, "intercept_policy_scan: %s, %s, policy_id = %d, action = %d(%s), maat_hit = %d, stream traceid is %s", + stream_addr, protocol_identify_res.domain, pmeinfo->policy_id, pmeinfo->action, action_str, pmeinfo->maat_hit, pmeinfo->stream_traceid); //receive client hello, but no syn/ack, bypass and dropme 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" : "", - pmeinfo->server_tcpopt == NULL ? "no syn/ack" : "", pmeinfo->stream_traceid); + 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" : "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_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_NO_SYN_ACK; 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){ 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_STM], 0, FS_OP_ADD, 1); return APP_STATE_FAWPKT | APP_STATE_GIVEME; case KNI_ACTION_INTERCEPT: - //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); - } - - //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; + return first_data_intercept(stream, pmeinfo, &pktinfo, stream_addr, thread_seq); default: //action != intercept && action != bypass,bypass and dropme 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); - //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->action, action_str, pmeinfo->policy_id, stream_addr, protocol_identify_res.domain); pmeinfo->error = STREAM_ERROR_INVALID_ACTION; 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 clock_gettime(CLOCK_REALTIME, &(pmeinfo->end_time)); void *logger = g_kni_handle->local_logger; @@ -838,13 +971,12 @@ static char close_opstate(const struct streaminfo *stream, struct pme_info *pmei strnlen(pmeinfo->stream_traceid, sizeof(pmeinfo->stream_traceid))); return APP_STATE_DROPPKT | APP_STATE_DROPME; case KNI_ACTION_BYPASS: - KNI_LOG_DEBUG(logger, "set tfe_release = 1, stream_trace_id is %s", pmeinfo->stream_traceid); + KNI_LOG_DEBUG(logger, "action is bypass, set tfe_release = 1, stream_trace_id is %s", pmeinfo->stream_traceid); pmeinfo->tfe_release = 1; return APP_STATE_FAWPKT | APP_STATE_DROPME; - //stream has only syn, ack. not data. do not send to tfe + //stream has only syn, ack. no data. default: - char action_str[KNI_SYMBOL_MAX]; - kni_maat_action_trans(pmeinfo->action, action_str); + char *action_str = kni_maat_action_trans(pmeinfo->action); 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); KNI_LOG_DEBUG(logger, "close_opstate: action %d(%s) is abnormal, stream_traceid is %s", @@ -857,37 +989,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){ 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; struct pme_info *pmeinfo = *(struct pme_info **)pme; - //pktinfo - struct pkt_info pktinfo; - memset(&pktinfo, 0, sizeof(pktinfo)); //TODO: 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_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 - //close: a_packet may be null, if a_packet = null, do not send to tfe + /* a_packet == NULL && not op_state_close, continue + close: a_packet may be null, if a_packet = null, do not send to tfe + */ 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_BYP_PKT], 0, FS_OP_ADD, 1); 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){ case OP_STATE_PENDING: *pme = pmeinfo = pme_info_new(stream, thread_seq); @@ -896,13 +1013,13 @@ extern "C" char kni_tcpall_entry(const struct streaminfo *stream, void** pme, in 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); - ret = pending_opstate(stream, pmeinfo, &pktinfo); + ret = pending_opstate(stream, pmeinfo, a_packet); if(pmeinfo->error < 0){ goto error_out; } break; 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 if(pmeinfo->error < 0){ goto error_out; @@ -910,14 +1027,13 @@ extern "C" char kni_tcpall_entry(const struct streaminfo *stream, void** pme, in break; case OP_STATE_CLOSE: //sapp stream close - ret = close_opstate(stream, pmeinfo, &pktinfo, thread_seq); + ret = close_opstate(stream, pmeinfo, thread_seq); if(pmeinfo->error < 0){ goto error_out; } 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 traceid is %s", stream->pktstate, pmeinfo->stream_traceid); break; @@ -930,7 +1046,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: - 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){ pme_info_destroy(pmeinfo); } @@ -989,7 +1106,6 @@ static void kni_marsio_destroy(struct kni_marsio_handle *handle){ handle = NULL; } - static void sendto_vxlan(marsio_buff_t *rx_buff, struct mr_sendpath *dev_vxlan_sendpath, int thread_seq){ //tag struct mr_tunnat_ctrlzone mr_ctrlzone; @@ -1018,29 +1134,61 @@ static long keepalive_replay_search_cb(void *data, const uchar *key, uint size, sendto_vxlan(rx_buff, marsio_handle->dev_vxlan_sendpath, thread_seq); return 0; } - //raw_packet: window update - struct iphdr *raw_packet_iphdr = args->raw_packet_iphdr; - int tot_len = ntohs(raw_packet_iphdr->tot_len); - int iphdr_len = raw_packet_iphdr->ihl * 4; - struct tcphdr *raw_packet_tcphdr = (struct tcphdr*)((char*)raw_packet_iphdr + iphdr_len); - //replay packet - char *replay_packet = ALLOC(char, tot_len); - memcpy(replay_packet, (void*)raw_packet_iphdr, 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); + //a_packet: window update + void *raw_packet = args->raw_packet; + char *replay_packet = NULL; + uint16_t tot_len = 0; + //ipv6 + if(args->addr_type == ADDR_TYPE_IPV6){ + + struct pkt_info raw_pktinfo; + int ret = kni_ipv6_header_parse(raw_packet, &raw_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_buff, marsio_handle->dev_vxlan_sendpath, thread_seq); + return 0; + } + tot_len = raw_pktinfo.ip_totlen; + replay_packet = ALLOC(char, tot_len); + memcpy(replay_packet, raw_packet, tot_len); + struct pkt_info replay_pktinfo; + kni_ipv6_header_parse(replay_packet, &replay_pktinfo); + 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 - 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, args->addr_type); if(ret < 0){ KNI_LOG_ERROR(logger, "Failed at send keepalive replay packet to tfe"); } @@ -1051,6 +1199,7 @@ static long keepalive_replay_search_cb(void *data, const uchar *key, uint size, } 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 kni_marsio_handle *marsio_handle = _args->marsio_handle; int thread_seq = _args->thread_seq; @@ -1069,26 +1218,52 @@ void* thread_tfe_data_receiver(void *args){ if(g_kni_handle->keepalive_replay_switch == 1){ for(int i = 0; i < nr_recv; i++){ struct ethhdr *ether_hdr = (struct ethhdr*)marsio_buff_mtod(rx_buffs[i]); - if(ether_hdr->h_proto == htons(ETH_P_IP)){ - struct iphdr *iphdr = (struct iphdr*)((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); + if(ether_hdr->h_proto == htons(ETH_P_IP) || ether_hdr->h_proto == htons(ETH_P_IPV6)){ + void *raw_packet = (char*)ether_hdr + sizeof(*ether_hdr); long cb_ret = -1; keepalive_replay_search_cb_args cb_args; memset(&cb_args, 0, sizeof(cb_args)); cb_args.rx_buff = rx_buffs[i]; cb_args.marsio_handle = marsio_handle; - cb_args.raw_packet_iphdr = iphdr; cb_args.tfe_id = i; cb_args.thread_seq = thread_seq; - MESA_htable_search_cb(g_kni_handle->keepalive_replay_htable, (const unsigned char *)(&key), - key_size, keepalive_replay_search_cb, &cb_args, &cb_ret); + //ipv4 + 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{ sendto_vxlan(rx_buffs[i], marsio_handle->dev_vxlan_sendpath, thread_seq); @@ -1105,6 +1280,7 @@ void* thread_tfe_data_receiver(void *args){ return NULL; } + 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 = 0; @@ -1446,6 +1622,11 @@ 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_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_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->fields[KNI_FIELD_EXCEED_MTU] = FS_register(handle, FS_STYLE_FIELD, FS_CALC_CURRENT, "exceed_mtu"); fs_handle->handle = handle; FS_start(handle); return fs_handle; @@ -1479,6 +1660,7 @@ static void keepalive_replay_data_free_cb(void *data) FREE(&data); } + extern "C" int kni_init(){ const char *profile = "./conf/kni/kni.conf"; const char *section = "global"; diff --git a/entry/src/kni_maat.cpp b/entry/src/kni_maat.cpp index 8fb63c4..75df092 100644 --- a/entry/src/kni_maat.cpp +++ b/entry/src/kni_maat.cpp @@ -32,7 +32,8 @@ void compile_ex_param_new(int idx, const struct Maat_rule_t* rule, const char* s void *logger = argp; KNI_LOG_INFO(logger, "call compile_ex_param_new"); 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; } @@ -245,34 +246,25 @@ enum kni_action intercept_policy_scan(struct kni_maat_handle* handle, struct ipa 0x60: steer 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){ case 0x00: - strcpy(action_str, "none"); - break; + return (char*)"none"; case 0x01: - strcpy(action_str, "monitor"); - break; + return (char*)"monitor"; case 0x02: - strcpy(action_str, "intercept"); - break; + return (char*)"intercept"; case 0x10: - strcpy(action_str, "reject"); - break; + return (char*)"reject"; case 0x30: - strcpy(action_str, "manipulate"); - break; + return (char*)"manipulate"; case 0x60: - strcpy(action_str, "steer"); - break; + return (char*)"steer"; case 0x80: - strcpy(action_str, "bypass"); - break; + return (char*)"bypass"; default: - strcpy(action_str, "unknown"); - break; + return (char*)"unknown"; } - return 0; }