Add GRE utils

This commit is contained in:
luwenpeng
2024-06-05 16:44:32 +08:00
parent 3ce5ed11db
commit a50ecb3dbb
5 changed files with 338 additions and 158 deletions

View File

@@ -6,12 +6,13 @@
#include "uthash.h"
#include "packet_priv.h"
#include "eth_utils.h"
#include "gre_utils.h"
#include "udp_utils.h"
#include "tcp_utils.h"
#include "ipv4_utils.h"
#include "ipv6_utils.h"
#include "mpls_utils.h"
#include "eth_utils.h"
#include "vlan_utils.h"
#include "vxlan_utils.h"
@@ -56,7 +57,6 @@ static inline void set_tuple6(const char *data, enum layer_type type, struct tup
static inline struct packet_layer *get_free_layer(struct packet *pkt);
static inline uint16_t get_gtp_hdr_len(const char *data, uint16_t len);
static inline uint16_t get_gre_hdr_len(const char *data, uint16_t len);
static inline uint16_t get_l2tpv2_hdr_len(const char *data, uint16_t len);
// 数据链路层
@@ -354,143 +354,6 @@ static inline uint16_t get_gtp_hdr_len(const char *data, uint16_t len)
return hdr_offset;
}
static inline uint16_t get_gre_hdr_len(const char *data, uint16_t len)
{
/*
* GRE Header Format (Version 0)
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |C|R|K|S|s|Recur| Flags | Ver | Protocol Type |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Checksum (optional) | Offset (optional) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Key (optional) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sequence Number (optional) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Routing (optional)
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Address Family | SRE Offset | SRE Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Routing Information ...
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* https://datatracker.ietf.org/doc/html/rfc1701
* https://datatracker.ietf.org/doc/html/rfc2890
*/
/*
* Enhanced GRE header (Version 1)
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |C|R|K|S|s|Recur|A| Flags | Ver | Protocol Type |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Key (HW) Payload Length | Key (LW) Call ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sequence Number (Optional) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Acknowledgment Number (Optional) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* https://datatracker.ietf.org/doc/html/rfc2637
*/
/* bit positions for flags in header */
#define GRE_CHECKSUM 0x8000
#define GRE_ROUTING 0x4000
#define GRE_KEY 0x2000
#define GRE_SEQUENCE 0x1000
#define GRE_STRICTSOURCE 0x0800
#define GRE_RECURSION 0x0700
#define GRE_ACK 0x0080 /* only in special PPTPized GRE header */
#define GRE_RESERVED_PPP 0x0078 /* only in special PPTPized GRE header */
#define GRE_RESERVED 0x00F8
#define GRE_VERSION 0x0007
if (len < 4)
{
return 0;
}
struct SRE
{
uint16_t address_family;
uint8_t sre_offset;
uint8_t sre_length;
} __attribute__((__packed__));
uint16_t sre_size = sizeof(struct SRE);
const uint16_t *gre = (const uint16_t *)data;
uint16_t flags = ntohs(gre[0]);
uint16_t version = flags & GRE_VERSION;
uint16_t hdr_offset = 0;
if (version == 0)
{
hdr_offset = 4;
if ((flags & GRE_CHECKSUM) || (flags & GRE_ROUTING))
{
hdr_offset += 4;
}
if (flags & GRE_KEY)
{
hdr_offset += 4;
}
if (flags & GRE_SEQUENCE)
{
hdr_offset += 4;
}
if (flags & GRE_ROUTING)
{
while (hdr_offset + sre_size <= len)
{
struct SRE *sre = (struct SRE *)((char *)data + hdr_offset);
if (sre->sre_length == 0)
{
hdr_offset += sre_size;
break;
}
else
{
hdr_offset += sre_size + sre->sre_length;
}
}
}
}
else if (version == 1)
{
hdr_offset = 8;
if (flags & GRE_SEQUENCE)
{
hdr_offset += 4;
}
if (flags & GRE_ACK)
{
hdr_offset += 4;
}
}
else
{
return 0;
}
if (hdr_offset > len)
{
return 0;
}
return hdr_offset;
}
static inline uint16_t get_l2tpv2_hdr_len(const char *data, uint16_t len)
{
/*
@@ -1049,12 +912,7 @@ static inline const char *parse_auth(struct packet *pkt, const char *data, uint1
static inline const char *parse_gre(struct packet *pkt, const char *data, uint16_t len)
{
#define GRE_PRO_IPV4 (0x0800)
#define GRE_PRO_IPV6 (0x86DD)
#define GRE_PRO_ARP (0x0806)
#define GRE_PRO_PPP (0x880B)
uint16_t hdr_len = get_gre_hdr_len(data, len);
uint16_t hdr_len = calc_gre_hdr_len(data, len);
if (unlikely(hdr_len == 0 || hdr_len > len))
{
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_TYPE_GRE);
@@ -1066,21 +924,10 @@ static inline const char *parse_gre(struct packet *pkt, const char *data, uint16
{
return data;
}
uint16_t next_proto = ntohs(*((uint16_t *)data + 1));
uint16_t next_proto = gre_hdr_get_proto((const struct gre_hdr *)data);
SET_LAYER(pkt, layer, LAYER_TYPE_GRE, hdr_len, data, len, 0);
switch (next_proto)
{
case GRE_PRO_IPV4:
return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len);
case GRE_PRO_IPV6:
return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len);
case GRE_PRO_PPP:
return parse_ppp(pkt, layer->pld_ptr, layer->pld_len);
default:
PACKET_LOG_UNSUPPORT_PROTO(pkt, LAYER_TYPE_GRE, next_proto);
return layer->pld_ptr;
}
return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len);
}
static inline const char *parse_udp(struct packet *pkt, const char *data, uint16_t len)
@@ -1283,6 +1130,8 @@ static inline const char *parse_l3(struct packet *pkt, uint16_t next_proto, cons
return parse_pppoe_ses(pkt, data, len);
case ETH_P_MPLS_UC:
return parse_mpls(pkt, data, len);
case 0x880b:
return parse_ppp(pkt, data, len);
default:
PACKET_LOG_UNSUPPORT_ETHPROTO(pkt, next_proto);
return data;
@@ -1384,6 +1233,7 @@ void packet_print_str(const struct packet *pkt)
case LAYER_TYPE_IPAH:
break;
case LAYER_TYPE_GRE:
used = gre_hdr_to_str((const struct gre_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
break;
case LAYER_TYPE_UDP:
used = udp_hdr_to_str((const struct udphdr *)layer->hdr_ptr, buffer, sizeof(buffer));