diff options
author | Maatuq <mahmoudmatook.mm@gmail.com> | 2023-04-04 16:20:11 +0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-04 14:20:11 +0200 |
commit | f1193d5e6f7680e6b8195eea33d740987619ac9c (patch) | |
tree | 23bc44c14eb5cb5c0c49799a9dae1e4541f7fa04 /example/reader_util.c | |
parent | cc5aec5f0ac6ff3d7d4c9ecbe02881641e8c8c92 (diff) |
add support for gre decapsulation (#1442) (#1921)
Diffstat (limited to 'example/reader_util.c')
-rw-r--r-- | example/reader_util.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/example/reader_util.c b/example/reader_util.c index 678b454b7..76e54900f 100644 --- a/example/reader_util.c +++ b/example/reader_util.c @@ -1791,6 +1791,74 @@ static inline u_int ndpi_skip_vxlan(u_int16_t ip_offset, u_int16_t ip_len){ return ip_offset + ip_len + sizeof(struct ndpi_udphdr) + sizeof(struct ndpi_vxlanhdr); } +static uint32_t ndpi_is_valid_gre_tunnel(const struct pcap_pkthdr *header, + const u_char *packet, const u_int16_t ip_offset, + const u_int16_t ip_len) { + if(header->caplen < ip_offset + ip_len + sizeof(struct ndpi_gre_basehdr)) + return 0; /* Too short for GRE header*/ + uint32_t offset = ip_offset + ip_len; + struct ndpi_gre_basehdr *grehdr = (struct ndpi_gre_basehdr*)&packet[offset]; + offset += sizeof(struct ndpi_gre_basehdr); + /* + rfc-1701 + The GRE flags are encoded in the first two octets. Bit 0 is the + most significant bit, bit 15 is the least significant bit. Bits + 13 through 15 are reserved for the Version field. Bits 5 through + 12 are reserved for future use and MUST be transmitted as zero. + */ + if(NDPI_GRE_IS_FLAGS(grehdr->flags)) + return 0; + if(NDPI_GRE_IS_REC(grehdr->flags)) + return 0; + /*GRE rfc 2890 that update 1701*/ + if(NDPI_GRE_IS_VERSION_0(grehdr->flags)) { + if(NDPI_GRE_IS_CSUM(grehdr->flags)) { + if(header->caplen < offset + 4) + return 0; + /*checksum field and offset field*/ + offset += 4; + } + if(NDPI_GRE_IS_KEY(grehdr->flags)) { + if(header->caplen < offset + 4) + return 0; + offset += 4; + } + if(NDPI_GRE_IS_SEQ(grehdr->flags)) { + if(header->caplen < offset + 4) + return 0; + offset += 4; + } + } else if(NDPI_GRE_IS_VERSION_1(grehdr->flags)) { /*rfc-2637 section 4.1 enhanced gre*/ + if(NDPI_GRE_IS_CSUM(grehdr->flags)) + return 0; + if(NDPI_GRE_IS_ROUTING(grehdr->flags)) + return 0; + if(!NDPI_GRE_IS_KEY(grehdr->flags)) + return 0; + if(NDPI_GRE_IS_STRICT(grehdr->flags)) + return 0; + if(grehdr->protocol != NDPI_GRE_PROTO_PPP) + return 0; + /*key field*/ + if(header->caplen < offset + 4) + return 0; + offset += 4; + if(NDPI_GRE_IS_SEQ(grehdr->flags)) { + if(header->caplen < offset + 4) + return 0; + offset += 4; + } + if(NDPI_GRE_IS_ACK(grehdr->flags)) { + if(header->caplen < offset + 4) + return 0; + offset += 4; + } + } else { /*support only ver 0, 1*/ + return 0; + } + return offset; +} + /* ****************************************************** */ struct ndpi_proto ndpi_workflow_process_packet(struct ndpi_workflow * workflow, @@ -2295,6 +2363,26 @@ struct ndpi_proto ndpi_workflow_process_packet(struct ndpi_workflow * workflow, goto datalink_check; } } + } else if(workflow->prefs.decode_tunnels && (proto == IPPROTO_GRE)) { + if(header->caplen < ip_offset + ip_len + sizeof(struct ndpi_gre_basehdr)) + return(nproto); /* Too short for GRE header*/ + u_int32_t offset = 0; + if((offset = ndpi_is_valid_gre_tunnel(header, packet, ip_offset, ip_len))) { + tunnel_type = ndpi_gre_tunnel; + struct ndpi_gre_basehdr *grehdr = (struct ndpi_gre_basehdr*)&packet[ip_offset + ip_len]; + if(grehdr->protocol == ntohs(ETH_P_IP) || grehdr->protocol == ntohs(ETH_P_IPV6)) { + ip_offset = offset; + goto iph_check; + } else if(grehdr->protocol == NDPI_GRE_PROTO_PPP) { // ppp protocol + ip_offset = offset + NDPI_PPP_HDRLEN; + goto iph_check; + } else { + eth_offset = offset; + goto datalink_check; + } + } else { + return(nproto); + } } /* process the packet */ |