From 240efaec395961ad55a85dd7f15fde784de1f065 Mon Sep 17 00:00:00 2001 From: yangwei Date: Thu, 26 Aug 2021 20:36:27 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(greedy=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=B7=B3=E8=BF=87gre):?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mesa_net.h | 6 ++ src/net_common.c | 269 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 273 insertions(+), 2 deletions(-) diff --git a/src/mesa_net.h b/src/mesa_net.h index ab46da4..67b9b6a 100644 --- a/src/mesa_net.h +++ b/src/mesa_net.h @@ -510,6 +510,12 @@ enum pptp_control_message_type{ PPTP_CTRL_SET_LINK_INFO = 15, }; +#define GRE_PRO_IPV4 (0x0800) +#define GRE_PRO_IPV6 (0x86DD) +#define GRE_PRO_ARP (0x0806) +#define GRE_PRO_PPP (0x880B) + + struct mesa_pptp_control_hdr{ unsigned short length; /* 全部数据长度, 包括本头部 */ unsigned short pptp_message_type; diff --git a/src/net_common.c b/src/net_common.c index c4b88fe..22a4e85 100644 --- a/src/net_common.c +++ b/src/net_common.c @@ -26,6 +26,7 @@ static int eth_jump_to_layer(const char *raw_data, int raw_layer_type, int expe static int vlan8021q_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type); static int ipv4_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type); static int ipv6_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type); +static int gre_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type); int treat_vlan_as_mac_in_mac_sw = 0; /* 将vlan强制按mac_in_mac格式解析, 先不传递给sapp, 因为影响sapp全局处理开关 */ @@ -80,6 +81,7 @@ static int arp_jump_to_layer(const char *raw_data, int raw_layer_type, int expe } + static int gtp_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type) { const struct gtp_hdr *gh = (struct gtp_hdr *)raw_data; @@ -235,6 +237,14 @@ static int ipv4_jump_to_layer(const char *raw_data, int raw_layer_type, int exp skip_len = ipv6_jump_to_layer(raw_data+ip_hdr_len, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type); } break; + case IPPROTO_GRE: + if((ADDR_TYPE_GRE == expect_layer_type) || (ADDR_TYPE_PPTP == expect_layer_type)){ + skip_len = 0; + break; + }else{ + skip_len = gre_jump_to_layer(raw_data+ip_hdr_len, ADDR_TYPE_GRE, expect_layer_type); + } + break; default: skip_len = -1; @@ -735,6 +745,253 @@ static int mac_in_mac_jump_to_layer(const char *raw_data, int raw_layer_type, i return layer_skip_len + sizeof(struct ethhdr) * 2; } +static inline int calc_gre_hdr_len_v0(const struct mesa_gre_base_hdr_v0 *gre_base_hdr_v0) +{ + int gre_hdr_len = sizeof(struct mesa_gre_base_hdr_v0); + + if(gre_base_hdr_v0->checksum_flag || gre_base_hdr_v0->route_flag){ + gre_hdr_len += sizeof(short) * 2; /* checksum and offset */ + } + + if(gre_base_hdr_v0->key_flag){ + gre_hdr_len += sizeof(int ); + } + + if(gre_base_hdr_v0->seq_flag){ + gre_hdr_len += sizeof(int ); + } + + return gre_hdr_len; +} + +static inline int calc_gre_hdr_len_v1(const struct mesa_gre_base_hdr_v1 *gre_base_hdr_v1) +{ + int gre_hdr_len = sizeof(struct mesa_gre_base_hdr_v1); + + if(gre_base_hdr_v1->checksum_flag != 0){ + printf("error! in gre version1, checksum flag not zero!\n"); + return -1; + } + + if(gre_base_hdr_v1->route_flag != 0){ + printf("error! in gre version1, route flag not zero!\n"); + return -1; + } + + if(gre_base_hdr_v1->recur != 0){ + printf("error! in gre version1, recur flag not zero!\n"); + return -1; + } + + if(gre_base_hdr_v1->strict_src_route_flag != 0){ + printf("error! in gre version1, strict_src_route flag not zero!\n"); + return -1; + } + + if(ntohs(gre_base_hdr_v1->protocol) != GRE_PRO_PPP){ + printf("error! in gre version1, protocol not 0x%x!\n", GRE_PRO_PPP); + return -1; + } + + gre_hdr_len += sizeof(short) * 2; /* payload_len and callid */ + + if(gre_base_hdr_v1->seq_flag){ + gre_hdr_len += sizeof(int); + } + + /* version 1 has ack number */ + if(gre_base_hdr_v1->ack_flag){ + gre_hdr_len += sizeof(int); + } + + return gre_hdr_len; +} + +int calc_gre_hdr_len(const struct mesa_gre_hdr *gre_hdr) +{ + int gre_hdr_len = -1; + + if(0 == gre_hdr->gre_base.version){ + gre_hdr_len = calc_gre_hdr_len_v0(&gre_hdr->gre_base); + }else if(1 == gre_hdr->gre_base.version){ + gre_hdr_len = calc_gre_hdr_len_v1((const struct mesa_gre_base_hdr_v1 *)&gre_hdr->gre_base); + }else{ + gre_hdr_len = -1; + } + + return gre_hdr_len; +} + +static int set_gre_hdr_ver0(struct mesa_gre_hdr *stack_gre_addr, const struct mesa_gre_hdr *net_gre_addr) +{ + struct mesa_gre_extend_hdr *stack_gre_ext = &stack_gre_addr->gre_extend; + const struct mesa_gre_base_hdr_v0 *net_gre_base = &net_gre_addr->gre_base; + const char *net_ext_hdr_value = (const char *)(&net_gre_addr->gre_extend); + //const struct gre_source_route_entry_hdr *rse_hdr; + + if(net_gre_base->checksum_flag || net_gre_base->route_flag){ + stack_gre_ext->checksum = *((unsigned short *)net_ext_hdr_value); + net_ext_hdr_value += sizeof(short); + + /* 如果checksum存在, 则offset也必存在 */ + stack_gre_ext->offset = *((unsigned short *)net_ext_hdr_value); + net_ext_hdr_value += sizeof(short); + } + + if(net_gre_base->key_flag){ + stack_gre_ext->key = *((unsigned int *)net_ext_hdr_value); + net_ext_hdr_value += sizeof(int); + } + + if(net_gre_base->seq_flag){ + stack_gre_ext->seq_num = *((unsigned int *)net_ext_hdr_value); + net_ext_hdr_value += sizeof(int); + } + + /* SRE信息在GRE头部的最后, 因为不定长, 不定数量 */ + if(net_gre_base->route_flag){ + //rse_hdr = (const struct gre_source_route_entry_hdr *)net_ext_hdr_value; + //TODO 1, copy SRE + printf("found GRE SRE data, but not parse yet, TODO!\n"); + return -1; + } + + return sizeof(struct mesa_gre_base_hdr_v1) + (net_ext_hdr_value - (char *)&net_gre_addr->gre_extend); +} + + +static int set_gre_hdr_ver1(struct mesa_gre_hdr *stack_gre_addr, const struct mesa_gre_hdr *net_gre_addr) +{ + //struct mesa_gre_base_hdr_v1 *stack_gre_base = (struct mesa_gre_base_hdr_v1 *)&stack_gre_addr->gre_base; + struct mesa_gre_extend_hdr *stack_gre_ext = &stack_gre_addr->gre_extend; + const struct mesa_gre_base_hdr_v1 *net_gre_base = (struct mesa_gre_base_hdr_v1 *)&net_gre_addr->gre_base; + //const struct mesa_gre_extend_hdr *net_gre_ext = &net_gre_addr->gre_extend; + const char *net_ext_hdr_value = (const char *)(&net_gre_addr->gre_extend); + + if(net_gre_base->checksum_flag != 0){ + printf("error! in gre version1, checksum flag not zero!\n"); + return -1; + } + + if(net_gre_base->route_flag != 0){ + printf("error! in gre version1, route flag not zero!\n"); + return -1; + } + + if(net_gre_base->recur != 0){ + printf("error! in gre version1, recur flag not zero!\n"); + return -1; + } + + if(net_gre_base->strict_src_route_flag != 0){ + printf("error! in gre version1, strict_src_route flag not zero!\n"); + return -1; + } + + if(ntohs(net_gre_base->protocol) != GRE_PRO_PPP){ + printf("error! in gre version1, protocol not 0x%x!\n", GRE_PRO_PPP); + return -1; + } + + stack_gre_ext->payload_len = *((unsigned short *)net_ext_hdr_value); + net_ext_hdr_value += sizeof(short); + + stack_gre_ext->call_id = *((unsigned short *)net_ext_hdr_value); + net_ext_hdr_value += sizeof(short); + + if(net_gre_base->seq_flag){ + stack_gre_ext->seq_num = *((unsigned int *)net_ext_hdr_value); + net_ext_hdr_value += sizeof(int); + } + + /* version 1 has ack number */ + if(net_gre_base->ack_flag){ + stack_gre_ext->ack_num = *((unsigned int *)net_ext_hdr_value); + net_ext_hdr_value += sizeof(int); + } + + return sizeof(struct mesa_gre_base_hdr_v1) + (net_ext_hdr_value - (char *)&net_gre_addr->gre_extend); +} + + +int set_gre_hdr(struct mesa_gre_hdr *stack_gre_addr, const void *this_layer_data) +{ + int gre_hdr_len = 0; + const struct mesa_gre_hdr *net_gre_addr = (const struct mesa_gre_hdr *)this_layer_data; + + memcpy(&stack_gre_addr->gre_base, &net_gre_addr->gre_base, sizeof(struct mesa_gre_base_hdr_v0)); + memset(&stack_gre_addr->gre_extend, 0, sizeof(struct mesa_gre_extend_hdr)); + + if(0 == net_gre_addr->gre_base.version){ + gre_hdr_len = set_gre_hdr_ver0(stack_gre_addr, net_gre_addr); + }else if(1 == net_gre_addr->gre_base.version){ + gre_hdr_len = set_gre_hdr_ver1(stack_gre_addr, net_gre_addr); + }else{ + //TODO 1, 未知版本 + printf("Unknown gre hdr version:%d\n", net_gre_addr->gre_base.version); + gre_hdr_len = -1; + } + + return gre_hdr_len; +} + +static int gre_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type) +{ + int skip_len = 0; + int this_gre_layer_len; + struct mesa_gre_hdr this_layer_hdr; + + if(raw_layer_type == expect_layer_type){ + return 0; + } + + this_gre_layer_len = set_gre_hdr(&this_layer_hdr, (void *)raw_data); + if(this_gre_layer_len < 0){ + return -1; + } + + switch(ntohs(this_layer_hdr.gre_base.protocol)) + { + case GRE_PRO_IPV4: + if(expect_layer_type == ADDR_TYPE_IPV4){ + skip_len = 0; + break; + }else{ + skip_len=ipv4_jump_to_layer(raw_data+this_gre_layer_len, __ADDR_TYPE_IP_PAIR_V4, expect_layer_type); + } + break; + + case GRE_PRO_IPV6: + if(expect_layer_type == ADDR_TYPE_IPV4){ + skip_len = 0; + break; + }else{ + skip_len=ipv6_jump_to_layer(raw_data+this_gre_layer_len, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type); + } + break; + + case GRE_PRO_PPP: + if((expect_layer_type == ADDR_TYPE_PPP) || (expect_layer_type == ADDR_TYPE_PPTP)){ + skip_len = this_gre_layer_len; + break; + }else{ + skip_len = ppp_jump_to_layer(raw_data+this_gre_layer_len, ADDR_TYPE_PPP, expect_layer_type); + } + break; + + default: + printf("gre_jump_to_layer(): unknown gre protocol:0x%x!\n", ntohs(this_layer_hdr.gre_base.protocol)); + return -1; + break; + } + + if(skip_len < 0){ + printf("gre_jump_to_layer() error!\n"); + return -1; + } + + return skip_len + this_gre_layer_len; +} /* return value: Non-NULL: the pointer to expect layer; @@ -803,8 +1060,13 @@ const void *MESA_net_jump_to_layer(const void *raw_data, int raw_layer_type, in ret = mpls_jump_to_layer((const char *)raw_data, raw_layer_type, expect_layer_type); break; - case ADDR_TYPE_PPPOE_SES: case ADDR_TYPE_GRE: + ret = gre_jump_to_layer((const char *)raw_data, raw_layer_type, expect_layer_type); + break; + + case ADDR_TYPE_PPPOE_SES: + return NULL; + break; default: printf("MESA_net_jump_to_layer(): unsupport raw_layer_type:%d in MESA_net_jump_to_layer()!\n", raw_layer_type); return NULL; @@ -848,8 +1110,11 @@ const void *MESA_net_jump_to_layer_greedy(const void *raw_data, int raw_layer_ty if(IPPROTO_UDP == ip4hdr->ip_p){ new_next_layer_data = (char *)expect_layer + ip4hdr->ip_hl * 4; new_raw_layer_type = ADDR_TYPE_UDP; /* IP层如果继续向下一层偏移, 只支持UDP, IPIP, GRE, L2TPv3. */ + }else if(IPPROTO_GRE == ip4hdr->ip_p){ + new_next_layer_data = (char *)expect_layer + ip4hdr->ip_hl * 4; + new_raw_layer_type = ADDR_TYPE_GRE; /* GRE */ }else{ - //TODO 2, GRE, IPIP, L2TPv3 + //TODO 2, IPIP, L2TPv3 goto done; } }