feature: add GRE utils, support overwrite checksum of GTPv0/GTPv1 header

This commit is contained in:
luwenpeng
2024-07-11 14:26:19 +08:00
parent 6d552acfd0
commit 9e338ffccb
8 changed files with 971 additions and 296 deletions

421
src/packet/gre0_utils.h Normal file
View File

@@ -0,0 +1,421 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include "eth_utils.h"
/*
* 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
*/
struct gre0_hdr
{
uint16_t flags;
uint16_t protocol;
};
struct sre
{
uint16_t family;
uint8_t offset;
uint8_t length;
};
#define GRE0_FLAG_CHECKSUM 0x8000
#define GRE0_FLAG_ROUTING 0x4000
#define GRE0_FLAG_KEY 0x2000
#define GRE0_FLAG_SEQUENCE 0x1000
#define GRE0_FLAG_STRICT 0x0800
#define GRE0_FLAG_RECURSION 0x0700
#define GRE0_FLAG_VERSION 0x0007
/******************************************************************************
* get
******************************************************************************/
static inline uint16_t gre0_hdr_get_flags(const struct gre0_hdr *hdr)
{
return ntohs(hdr->flags);
}
static inline uint8_t gre0_hdr_get_checksum_flag(const struct gre0_hdr *hdr)
{
return (ntohs(hdr->flags) & GRE0_FLAG_CHECKSUM) >> 15;
}
static inline uint8_t gre0_hdr_get_routing_flag(const struct gre0_hdr *hdr)
{
return (ntohs(hdr->flags) & GRE0_FLAG_ROUTING) >> 14;
}
static inline uint8_t gre0_hdr_get_key_flag(const struct gre0_hdr *hdr)
{
return (ntohs(hdr->flags) & GRE0_FLAG_KEY) >> 13;
}
static inline uint8_t gre0_hdr_get_seq_flag(const struct gre0_hdr *hdr)
{
return (ntohs(hdr->flags) & GRE0_FLAG_SEQUENCE) >> 12;
}
static inline uint8_t gre0_hdr_get_strict_flag(const struct gre0_hdr *hdr)
{
return (ntohs(hdr->flags) & GRE0_FLAG_STRICT) >> 11;
}
static inline uint8_t gre0_hdr_get_version(const struct gre0_hdr *hdr)
{
return ntohs(hdr->flags) & GRE0_FLAG_VERSION;
}
// ethernet protocol
static inline uint16_t gre0_hdr_get_proto(const struct gre0_hdr *hdr)
{
return ntohs(hdr->protocol);
}
static inline uint16_t gre0_hdr_get_checksum(const struct gre0_hdr *hdr)
{
if (gre0_hdr_get_checksum_flag(hdr))
{
const char *ptr = ((const char *)hdr) + 4;
return ntohs(*(uint16_t *)ptr);
}
else
{
return 0;
}
}
static inline uint16_t gre0_hdr_get_offset(const struct gre0_hdr *hdr)
{
if (gre0_hdr_get_checksum_flag(hdr))
{
const char *ptr = ((const char *)hdr) + 6;
return ntohs(*(uint16_t *)ptr);
}
else
{
return 0;
}
}
static inline uint32_t gre0_hdr_get_key(const struct gre0_hdr *hdr)
{
if (gre0_hdr_get_key_flag(hdr))
{
const char *ptr = ((const char *)hdr) + 4;
if (gre0_hdr_get_checksum_flag(hdr))
{
ptr += 4;
}
return ntohl(*(uint32_t *)ptr);
}
else
{
return 0;
}
}
static inline uint32_t gre0_hdr_get_seq(const struct gre0_hdr *hdr)
{
if (gre0_hdr_get_seq_flag(hdr))
{
const char *ptr = ((const char *)hdr) + 4;
if (gre0_hdr_get_checksum_flag(hdr))
{
ptr += 4;
}
if (gre0_hdr_get_key_flag(hdr))
{
ptr += 4;
}
return ntohl(*(uint32_t *)ptr);
}
else
{
return 0;
}
}
static inline const char *gre0_hdr_get_routing_data(const struct gre0_hdr *hdr)
{
if (gre0_hdr_get_routing_flag(hdr))
{
const char *ptr = ((const char *)hdr) + 4;
if (gre0_hdr_get_checksum_flag(hdr))
{
ptr += 4;
}
if (gre0_hdr_get_key_flag(hdr))
{
ptr += 4;
}
if (gre0_hdr_get_seq_flag(hdr))
{
ptr += 4;
}
return ptr;
}
else
{
return NULL;
}
}
static inline uint16_t gre0_hdr_get_routing_len(const struct gre0_hdr *hdr)
{
if (gre0_hdr_get_routing_flag(hdr))
{
const char *ptr = gre0_hdr_get_routing_data(hdr);
uint16_t hdr_len = 0;
while (1)
{
struct sre *sre = (struct sre *)(ptr + hdr_len);
if (sre->length == 0)
{
hdr_len += sizeof(struct sre);
break;
}
else
{
hdr_len += sizeof(struct sre) + sre->length;
}
}
return hdr_len;
}
else
{
return 0;
}
}
static inline uint16_t calc_gre0_hdr_len(const char *data, uint32_t len)
{
const struct gre0_hdr *hdr = (const struct gre0_hdr *)data;
uint16_t hdr_len = 4;
uint16_t flags = ntohs(hdr->flags);
if ((flags & GRE0_FLAG_CHECKSUM) || (flags & GRE0_FLAG_ROUTING))
{
hdr_len += 4; // skip checksum and offset fields
}
if (flags & GRE0_FLAG_KEY)
{
hdr_len += 4; // skip key field
}
if (flags & GRE0_FLAG_SEQUENCE)
{
hdr_len += 4; // skip sequence number field
}
if (flags & GRE0_FLAG_ROUTING)
{
while (hdr_len + sizeof(struct sre) <= len)
{
struct sre *sre = (struct sre *)((char *)data + hdr_len);
if (sre->length == 0)
{
hdr_len += sizeof(struct sre);
break;
}
else
{
hdr_len += sizeof(struct sre) + sre->length;
}
}
}
return hdr_len;
}
/******************************************************************************
* set
******************************************************************************/
static inline void gre0_hdr_set_flags(struct gre0_hdr *hdr, uint16_t flags)
{
hdr->flags = htons(flags);
}
static inline void gre0_hdr_set_checksum_flag(struct gre0_hdr *hdr, uint8_t flag)
{
hdr->flags = htons((ntohs(hdr->flags) & ~GRE0_FLAG_CHECKSUM) | flag << 15);
}
static inline void gre0_hdr_set_routing_flag(struct gre0_hdr *hdr, uint8_t flag)
{
hdr->flags = htons((ntohs(hdr->flags) & ~GRE0_FLAG_ROUTING) | flag << 14);
}
static inline void gre0_hdr_set_key_flag(struct gre0_hdr *hdr, uint8_t flag)
{
hdr->flags = htons((ntohs(hdr->flags) & ~GRE0_FLAG_KEY) | flag << 13);
}
static inline void gre0_hdr_set_seq_flag(struct gre0_hdr *hdr, uint8_t flag)
{
hdr->flags = htons((ntohs(hdr->flags) & ~GRE0_FLAG_SEQUENCE) | flag << 12);
}
static inline void gre0_hdr_set_strict_flag(struct gre0_hdr *hdr, uint8_t flag)
{
hdr->flags = htons((ntohs(hdr->flags) & ~GRE0_FLAG_STRICT) | flag << 11);
}
static inline void gre0_hdr_set_version(struct gre0_hdr *hdr, uint8_t version)
{
hdr->flags = htons((ntohs(hdr->flags) & ~GRE0_FLAG_VERSION) | version);
}
static inline void gre0_hdr_set_proto(struct gre0_hdr *hdr, uint16_t proto)
{
hdr->protocol = htons(proto);
}
static inline void gre0_hdr_set_checksum(struct gre0_hdr *hdr, uint16_t checksum)
{
if (gre0_hdr_get_checksum_flag(hdr))
{
char *ptr = ((char *)hdr) + 4;
*(uint16_t *)ptr = htons(checksum);
}
}
static inline void gre0_hdr_set_offset(struct gre0_hdr *hdr, uint16_t offset)
{
if (gre0_hdr_get_checksum_flag(hdr))
{
char *ptr = ((char *)hdr) + 6;
*(uint16_t *)ptr = htons(offset);
}
}
static inline void gre0_hdr_set_key(struct gre0_hdr *hdr, uint32_t key)
{
if (gre0_hdr_get_key_flag(hdr))
{
char *ptr = ((char *)hdr) + 4;
if (gre0_hdr_get_checksum_flag(hdr))
{
ptr += 4;
}
*(uint32_t *)ptr = htonl(key);
}
}
static inline void gre0_hdr_set_seq(struct gre0_hdr *hdr, uint32_t sequence)
{
if (gre0_hdr_get_seq_flag(hdr))
{
char *ptr = ((char *)hdr) + 4;
if (gre0_hdr_get_checksum_flag(hdr))
{
ptr += 4;
}
if (gre0_hdr_get_key_flag(hdr))
{
ptr += 4;
}
*(uint32_t *)ptr = htonl(sequence);
}
}
static inline void gre0_hdr_set_routing_data(struct gre0_hdr *hdr, const char *data, uint16_t len)
{
if (gre0_hdr_get_routing_flag(hdr))
{
char *ptr = ((char *)hdr) + 4;
if (gre0_hdr_get_checksum_flag(hdr))
{
ptr += 4;
}
if (gre0_hdr_get_key_flag(hdr))
{
ptr += 4;
}
if (gre0_hdr_get_seq_flag(hdr))
{
ptr += 4;
}
memcpy(ptr, data, len);
}
}
/******************************************************************************
* print
******************************************************************************/
static inline int gre0_hdr_to_str(const struct gre0_hdr *hdr, char *buf, size_t size)
{
memset(buf, 0, size);
int used = 0;
uint16_t proto = gre0_hdr_get_proto(hdr);
used += snprintf(buf + used, size - used, "GRE: flags=0x%04x (checksum_flag=%u, routing_flag=%u, key_flag=%u, seq_flag=%u, strict_flag=%u, version=%u), proto=%s",
gre0_hdr_get_flags(hdr), gre0_hdr_get_checksum_flag(hdr), gre0_hdr_get_routing_flag(hdr), gre0_hdr_get_key_flag(hdr),
gre0_hdr_get_seq_flag(hdr), gre0_hdr_get_strict_flag(hdr), gre0_hdr_get_version(hdr), eth_proto_to_str(proto));
if (gre0_hdr_get_checksum_flag(hdr))
{
used += snprintf(buf + used, size - used, ", checksum=%u, offset=%u", gre0_hdr_get_checksum(hdr), gre0_hdr_get_offset(hdr));
}
if (gre0_hdr_get_key_flag(hdr))
{
used += snprintf(buf + used, size - used, ", key=%u", gre0_hdr_get_key(hdr));
}
if (gre0_hdr_get_seq_flag(hdr))
{
used += snprintf(buf + used, size - used, ", seq=%u", gre0_hdr_get_seq(hdr));
}
if (gre0_hdr_get_routing_flag(hdr))
{
used += snprintf(buf + used, size - used, ", routing_len=%u", gre0_hdr_get_routing_len(hdr));
}
return used;
}
#ifdef __cplusplus
}
#endif

222
src/packet/gre1_utils.h Normal file
View File

@@ -0,0 +1,222 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include "eth_utils.h"
/*
* 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
*/
struct gre1_hdr
{
uint16_t flags;
uint16_t protocol;
uint16_t payload_length;
uint16_t call_id;
};
#define GRE1_FLAG_CHECKSUM 0x8000
#define GRE1_FLAG_ROUTING 0x4000
#define GRE1_FLAG_KEY 0x2000
#define GRE1_FLAG_SEQUENCE 0x1000
#define GRE1_FLAG_STRICT 0x0800
#define GRE1_FLAG_RECURSION 0x0700
#define GRE1_FLAG_ACK 0x0080 /* only in special PPTPized GRE header */
#define GRE1_FLAG_VERSION 0x0007
/******************************************************************************
* get
******************************************************************************/
static inline uint16_t gre1_hdr_get_flags(const struct gre1_hdr *hdr)
{
return ntohs(hdr->flags);
}
static inline uint8_t gre1_hdr_get_seq_flag(const struct gre1_hdr *hdr)
{
return (ntohs(hdr->flags) & GRE1_FLAG_SEQUENCE) >> 12;
}
static inline uint8_t gre1_hdr_get_ack_flag(const struct gre1_hdr *hdr)
{
return (ntohs(hdr->flags) & GRE1_FLAG_ACK) >> 7;
}
static inline uint8_t gre1_hdr_get_version(const struct gre1_hdr *hdr)
{
return ntohs(hdr->flags) & GRE1_FLAG_VERSION;
}
// ethernet protocol type
static inline uint16_t gre1_hdr_get_proto(const struct gre1_hdr *hdr)
{
return ntohs(hdr->protocol);
}
static inline uint16_t gre1_hdr_get_payload_length(const struct gre1_hdr *hdr)
{
return ntohs(hdr->payload_length);
}
static inline uint16_t gre1_hdr_get_call_id(const struct gre1_hdr *hdr)
{
return ntohs(hdr->call_id);
}
static inline uint32_t gre1_hdr_get_seq(const struct gre1_hdr *hdr)
{
if (gre1_hdr_get_seq_flag(hdr))
{
const char *ptr = ((const char *)hdr) + 8;
return ntohl(*((uint32_t *)ptr));
}
else
{
return 0;
}
}
static inline uint32_t gre1_hdr_get_ack(const struct gre1_hdr *hdr)
{
if (gre1_hdr_get_ack_flag(hdr))
{
const char *ptr = ((const char *)hdr) + 8;
if (gre1_hdr_get_seq_flag(hdr))
{
ptr += 4;
}
return ntohl(*((uint32_t *)ptr));
}
else
{
return 0;
}
}
static inline uint16_t calc_gre1_hdr_len(const char *data, uint32_t len)
{
const struct gre1_hdr *hdr = (const struct gre1_hdr *)data;
uint16_t hdr_len = 8;
uint16_t flags = gre1_hdr_get_flags(hdr);
if (flags & GRE1_FLAG_SEQUENCE)
{
hdr_len += 4;
}
if (flags & GRE1_FLAG_ACK)
{
hdr_len += 4;
}
return hdr_len;
}
/******************************************************************************
* set
******************************************************************************/
static inline void gre1_hdr_set_flags(struct gre1_hdr *hdr, uint16_t flags)
{
hdr->flags = htons(flags);
}
static inline void gre1_hdr_set_seq_flag(struct gre1_hdr *hdr, uint8_t seq_flag)
{
hdr->flags = htons((ntohs(hdr->flags) & ~GRE1_FLAG_SEQUENCE) | seq_flag << 12);
}
static inline void gre1_hdr_set_ack_flag(struct gre1_hdr *hdr, uint8_t ack_flag)
{
hdr->flags = htons((ntohs(hdr->flags) & ~GRE1_FLAG_ACK) | ack_flag << 7);
}
static inline void gre1_hdr_set_version(struct gre1_hdr *hdr, uint8_t version)
{
hdr->flags = htons((ntohs(hdr->flags) & ~GRE1_FLAG_VERSION) | version);
}
static inline void gre1_hdr_set_proto(struct gre1_hdr *hdr, uint16_t proto)
{
hdr->protocol = htons(proto);
}
static inline void gre1_hdr_set_payload_length(struct gre1_hdr *hdr, uint16_t payload_length)
{
hdr->payload_length = htons(payload_length);
}
static inline void gre1_hdr_set_call_id(struct gre1_hdr *hdr, uint16_t call_id)
{
hdr->call_id = htons(call_id);
}
static inline void gre1_hdr_set_seq(struct gre1_hdr *hdr, uint32_t seq)
{
if (gre1_hdr_get_seq_flag(hdr))
{
char *ptr = ((char *)hdr) + 8;
*((uint32_t *)ptr) = htonl(seq);
}
}
static inline void gre1_hdr_set_ack(struct gre1_hdr *hdr, uint32_t ack)
{
if (gre1_hdr_get_ack_flag(hdr))
{
char *ptr = ((char *)hdr) + 8;
if (gre1_hdr_get_seq_flag(hdr))
{
ptr += 4;
}
*((uint32_t *)ptr) = htonl(ack);
}
}
/******************************************************************************
* print
******************************************************************************/
static inline int gre1_hdr_to_str(const struct gre1_hdr *hdr, char *buf, size_t size)
{
memset(buf, 0, size);
int used = 0;
uint16_t proto = gre1_hdr_get_proto(hdr);
used += snprintf(buf + used, size - used, "GRE: flags=0x%04x (seq_flag=%u ack_flag=%u version=%u), proto=%s, payload_length=%u, call_id=%u",
gre1_hdr_get_flags(hdr), gre1_hdr_get_seq_flag(hdr), gre1_hdr_get_ack_flag(hdr), gre1_hdr_get_version(hdr),
eth_proto_to_str(proto), gre1_hdr_get_payload_length(hdr), gre1_hdr_get_call_id(hdr));
if (gre1_hdr_get_seq_flag(hdr))
{
used += snprintf(buf + used, size - used, ", seq=%u", gre1_hdr_get_seq(hdr));
}
if (gre1_hdr_get_ack_flag(hdr))
{
used += snprintf(buf + used, size - used, ", ack=%u", gre1_hdr_get_ack(hdr));
}
return used;
}
#ifdef __cplusplus
}
#endif

View File

@@ -5,174 +5,63 @@ extern "C"
{ {
#endif #endif
#include <stdio.h> #include "gre0_utils.h"
#include <string.h> #include "gre1_utils.h"
#include <arpa/inet.h>
#include "eth_utils.h"
/* #ifndef MIN
* GRE Header Format (Version 0) #define MIN(x, y) ((x) < (y) ? (x) : (y))
* #endif
* 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
*/
/* // return GRE version 0 or 1
* Enhanced GRE header (Version 1) // return 255 if not GRE
* static inline uint8_t peek_gre_version(const char *data, uint32_t len)
* 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
*/
struct gre_hdr
{ {
uint16_t flags_ver; if (len < MIN(sizeof(struct gre0_hdr), sizeof(struct gre1_hdr)))
uint16_t protocol; {
}; return 255;
}
struct sre uint16_t flag = *(uint16_t *)data;
{ return ntohs(flag) & 0x0007;
uint16_t address_family;
uint8_t sre_offset;
uint8_t sre_length;
};
#define GRE_CHECKSUM 0x8000
#define GRE_ROUTING 0x4000
#define GRE_KEY 0x2000
#define GRE_SEQUENCE 0x1000
#define GRE_ACK 0x0080 /* only in special PPTPized GRE header */
/******************************************************************************
* get
******************************************************************************/
static inline uint8_t gre_hdr_get_ver(const struct gre_hdr *hdr)
{
return ntohs(hdr->flags_ver) & 0x07;
} }
// ethernet protocol type static inline uint16_t peek_gre_proto(const char *data, uint32_t len)
static inline uint16_t gre_hdr_get_proto(const struct gre_hdr *hdr)
{ {
return ntohs(hdr->protocol); switch (peek_gre_version(data, len))
}
static inline uint16_t calc_grev0_hdr_len(const char *data, uint32_t len)
{
const struct gre_hdr *hdr = (const struct gre_hdr *)data;
uint16_t hdr_len = 4;
uint16_t flags = ntohs(hdr->flags_ver);
if ((flags & GRE_CHECKSUM) || (flags & GRE_ROUTING))
{
hdr_len += 4; // skip checksum and offset fields
}
if (flags & GRE_KEY)
{
hdr_len += 4; // skip key field
}
if (flags & GRE_SEQUENCE)
{
hdr_len += 4; // skip sequence number field
}
if (flags & GRE_ROUTING)
{
while (hdr_len + sizeof(struct sre) <= len)
{
struct sre *sre = (struct sre *)((char *)data + hdr_len);
if (sre->sre_length == 0)
{
hdr_len += sizeof(struct sre);
break;
}
else
{
hdr_len += sizeof(struct sre) + sre->sre_length;
}
}
}
return hdr_len;
}
static inline uint16_t calc_grev1_hdr_len(const char *data, uint32_t len)
{
const struct gre_hdr *hdr = (const struct gre_hdr *)data;
uint16_t hdr_len = 8;
uint16_t flags = ntohs(hdr->flags_ver);
if (flags & GRE_SEQUENCE)
{
hdr_len += 4;
}
if (flags & GRE_ACK)
{
hdr_len += 4;
}
return hdr_len;
}
static inline uint16_t calc_gre_hdr_len(const char *data, uint32_t len)
{
const struct gre_hdr *hdr = (const struct gre_hdr *)data;
switch (gre_hdr_get_ver(hdr))
{ {
case 0: case 0:
return calc_grev0_hdr_len(data, len); return gre0_hdr_get_proto((const struct gre0_hdr *)data);
case 1: case 1:
return calc_grev1_hdr_len(data, len); return gre1_hdr_get_proto((const struct gre1_hdr *)data);
default: default:
return 0; return 0;
} }
} }
/****************************************************************************** static inline uint16_t calc_gre_hdr_len(const char *data, uint32_t len)
* set
******************************************************************************/
// TODO
/******************************************************************************
* print
******************************************************************************/
static inline int gre_hdr_to_str(const struct gre_hdr *hdr, char *buf, size_t size)
{ {
memset(buf, 0, size); switch (peek_gre_version(data, len))
uint16_t proto = gre_hdr_get_proto(hdr); {
return snprintf(buf, size, "GRE: version=%u proto=%s", case 0:
gre_hdr_get_ver(hdr), eth_proto_to_str(proto)); return calc_gre0_hdr_len(data, len);
case 1:
return calc_gre1_hdr_len(data, len);
default:
return 0;
}
}
static inline int gre_hdr_to_str(const char *hdr, uint16_t len, char *buf, size_t size)
{
switch (peek_gre_version(hdr, len))
{
case 0:
return gre0_hdr_to_str((const struct gre0_hdr *)hdr, buf, size);
case 1:
return gre1_hdr_to_str((const struct gre1_hdr *)hdr, buf, size);
default:
return 0;
}
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -25,8 +25,11 @@ target_link_libraries(gtest_vlan_utils packet gtest)
add_executable(gtest_vxlan_utils gtest_vxlan_utils.cpp) add_executable(gtest_vxlan_utils gtest_vxlan_utils.cpp)
target_link_libraries(gtest_vxlan_utils packet gtest) target_link_libraries(gtest_vxlan_utils packet gtest)
add_executable(gtest_gre_utils gtest_gre_utils.cpp) add_executable(gtest_gre0_utils gtest_gre0_utils.cpp)
target_link_libraries(gtest_gre_utils packet gtest) target_link_libraries(gtest_gre0_utils packet gtest)
add_executable(gtest_gre1_utils gtest_gre1_utils.cpp)
target_link_libraries(gtest_gre1_utils packet gtest)
add_executable(gtest_l2tp_utils gtest_l2tp_utils.cpp) add_executable(gtest_l2tp_utils gtest_l2tp_utils.cpp)
target_link_libraries(gtest_l2tp_utils packet gtest) target_link_libraries(gtest_l2tp_utils packet gtest)
@@ -59,7 +62,8 @@ gtest_discover_tests(gtest_mpls_utils)
gtest_discover_tests(gtest_eth_utils) gtest_discover_tests(gtest_eth_utils)
gtest_discover_tests(gtest_vlan_utils) gtest_discover_tests(gtest_vlan_utils)
gtest_discover_tests(gtest_vxlan_utils) gtest_discover_tests(gtest_vxlan_utils)
gtest_discover_tests(gtest_gre_utils) gtest_discover_tests(gtest_gre0_utils)
gtest_discover_tests(gtest_gre1_utils)
gtest_discover_tests(gtest_l2tp_utils) gtest_discover_tests(gtest_l2tp_utils)
gtest_discover_tests(gtest_gtp1_utils) gtest_discover_tests(gtest_gtp1_utils)
gtest_discover_tests(gtest_gtp2_utils) gtest_discover_tests(gtest_gtp2_utils)

View File

@@ -0,0 +1,210 @@
#include <gtest/gtest.h>
#include "gre0_utils.h"
/*
* Generic Routing Encapsulation (IP)
* Flags and Version: 0x0000
* 0... .... .... .... = Checksum Bit: No
* .0.. .... .... .... = Routing Bit: No
* ..0. .... .... .... = Key Bit: No
* ...0 .... .... .... = Sequence Number Bit: No
* .... 0... .... .... = Strict Source Route Bit: No
* .... .000 .... .... = Recursion control: 0
* .... .... 0000 0... = Flags (Reserved): 0
* .... .... .... .000 = Version: GRE (0)
* Protocol Type: IP (0x0800)
*/
unsigned char gre0_no_opt[] = {
0x00, 0x00, 0x08, 0x00};
TEST(GRE0_UTILS, GET_1)
{
const struct gre0_hdr *hdr = (struct gre0_hdr *)gre0_no_opt;
EXPECT_TRUE(gre0_hdr_get_flags(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_checksum_flag(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_routing_flag(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_key_flag(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_seq_flag(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_strict_flag(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_version(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_proto(hdr) == 0x0800);
EXPECT_TRUE(gre0_hdr_get_checksum(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_offset(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_key(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_seq(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_routing_data(hdr) == NULL);
EXPECT_TRUE(gre0_hdr_get_routing_len(hdr) == 0);
EXPECT_TRUE(calc_gre0_hdr_len((const char *)gre0_no_opt, sizeof(gre0_no_opt)) == 4);
}
TEST(GRE0_UTILS, SET_1)
{
char buff[4] = {0};
struct gre0_hdr *hdr = (struct gre0_hdr *)buff;
gre0_hdr_set_flags(hdr, 0);
gre0_hdr_set_checksum_flag(hdr, 0);
gre0_hdr_set_routing_flag(hdr, 0);
gre0_hdr_set_key_flag(hdr, 0);
gre0_hdr_set_seq_flag(hdr, 0);
gre0_hdr_set_strict_flag(hdr, 0);
gre0_hdr_set_version(hdr, 0);
gre0_hdr_set_proto(hdr, 0x0800);
gre0_hdr_set_checksum(hdr, 0);
gre0_hdr_set_offset(hdr, 0);
gre0_hdr_set_key(hdr, 0);
gre0_hdr_set_seq(hdr, 0);
gre0_hdr_set_routing_data(hdr, NULL, 0);
EXPECT_TRUE(memcmp(buff, gre0_no_opt, 4) == 0);
}
/*
* Generic Routing Encapsulation (IP)
* Flags and Version: 0x2000
* 0... .... .... .... = Checksum Bit: No
* .0.. .... .... .... = Routing Bit: No
* ..1. .... .... .... = Key Bit: Yes
* ...0 .... .... .... = Sequence Number Bit: No
* .... 0... .... .... = Strict Source Route Bit: No
* .... .000 .... .... = Recursion control: 0
* .... .... 0000 0... = Flags (Reserved): 0
* .... .... .... .000 = Version: GRE (0)
* Protocol Type: IP (0x0800)
* Key: 0x00000384
*/
unsigned char gre0_opt_key[] = {0x20, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x84};
TEST(GRE0_UTILS, GET_2)
{
const struct gre0_hdr *hdr = (struct gre0_hdr *)gre0_opt_key;
EXPECT_TRUE(gre0_hdr_get_flags(hdr) == 0x2000);
EXPECT_TRUE(gre0_hdr_get_checksum_flag(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_routing_flag(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_key_flag(hdr) == 1);
EXPECT_TRUE(gre0_hdr_get_seq_flag(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_strict_flag(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_version(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_proto(hdr) == 0x0800);
EXPECT_TRUE(gre0_hdr_get_checksum(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_offset(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_key(hdr) == 0x00000384);
EXPECT_TRUE(gre0_hdr_get_seq(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_routing_data(hdr) == NULL);
EXPECT_TRUE(gre0_hdr_get_routing_len(hdr) == 0);
EXPECT_TRUE(calc_gre0_hdr_len((const char *)gre0_opt_key, sizeof(gre0_opt_key)) == 8);
}
TEST(GRE0_UTILS, SET_2)
{
char buff[8] = {0};
struct gre0_hdr *hdr = (struct gre0_hdr *)buff;
gre0_hdr_set_flags(hdr, 0x2000);
gre0_hdr_set_checksum_flag(hdr, 0);
gre0_hdr_set_routing_flag(hdr, 0);
gre0_hdr_set_key_flag(hdr, 1);
gre0_hdr_set_seq_flag(hdr, 0);
gre0_hdr_set_strict_flag(hdr, 0);
gre0_hdr_set_version(hdr, 0);
gre0_hdr_set_proto(hdr, 0x0800);
gre0_hdr_set_checksum(hdr, 0);
gre0_hdr_set_offset(hdr, 0);
gre0_hdr_set_key(hdr, 0x00000384);
gre0_hdr_set_seq(hdr, 0);
gre0_hdr_set_routing_data(hdr, NULL, 0);
EXPECT_TRUE(memcmp(buff, gre0_opt_key, 8) == 0);
}
/*
* Generic Routing Encapsulation (IP)
* Flags and Version: 0xc000
* 1... .... .... .... = Checksum Bit: Yes
* .1.. .... .... .... = Routing Bit: Yes
* ..0. .... .... .... = Key Bit: No
* ...0 .... .... .... = Sequence Number Bit: No
* .... 0... .... .... = Strict Source Route Bit: No
* .... .000 .... .... = Recursion control: 0
* .... .... 0000 0... = Flags (Reserved): 0
* .... .... .... .000 = Version: GRE (0)
* Protocol Type: IP (0x0800)
* Checksum: 0x0000 incorrect, should be 0xea95
* [Expert Info (Warning/Protocol): Incorrect GRE Checksum [should be 0xea95]]
* [Incorrect GRE Checksum [should be 0xea95]]
* [Severity level: Warning]
* [Group: Protocol]
* [Checksum Status: Bad]
* Offset: 44
* Routing
* Address Family: 2
* SRE Offset: 0
* SRE Length: 44
* Routing Information: 6c696e6b5f696e666f206c696e6b5f696e666f206c696e6b5f696e666f206c696e6b5f696e666f2000000000
* Routing
* Address Family: 0
* SRE Offset: 0
* SRE Length: 0
*/
unsigned char gre0_opt_chek_rout[] = {
0xc0, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x2c, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b,
0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
TEST(GRE0_UTILS, GET_3)
{
const struct gre0_hdr *hdr = (struct gre0_hdr *)gre0_opt_chek_rout;
EXPECT_TRUE(gre0_hdr_get_flags(hdr) == 0xc000);
EXPECT_TRUE(gre0_hdr_get_checksum_flag(hdr) == 1);
EXPECT_TRUE(gre0_hdr_get_routing_flag(hdr) == 1);
EXPECT_TRUE(gre0_hdr_get_key_flag(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_seq_flag(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_strict_flag(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_version(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_proto(hdr) == 0x0800);
EXPECT_TRUE(gre0_hdr_get_checksum(hdr) == 0x0000);
EXPECT_TRUE(gre0_hdr_get_offset(hdr) == 44);
EXPECT_TRUE(gre0_hdr_get_key(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_seq(hdr) == 0);
EXPECT_TRUE(gre0_hdr_get_routing_data(hdr) == (const char *)gre0_opt_chek_rout + 8);
EXPECT_TRUE(gre0_hdr_get_routing_len(hdr) == 52);
EXPECT_TRUE(calc_gre0_hdr_len((const char *)gre0_opt_chek_rout, sizeof(gre0_opt_chek_rout)) == 60);
}
TEST(GRE0_UTILS, SET_3)
{
char buff[60] = {0};
struct gre0_hdr *hdr = (struct gre0_hdr *)buff;
gre0_hdr_set_flags(hdr, 0xc000);
gre0_hdr_set_checksum_flag(hdr, 1);
gre0_hdr_set_routing_flag(hdr, 1);
gre0_hdr_set_key_flag(hdr, 0);
gre0_hdr_set_seq_flag(hdr, 0);
gre0_hdr_set_strict_flag(hdr, 0);
gre0_hdr_set_version(hdr, 0);
gre0_hdr_set_proto(hdr, 0x0800);
gre0_hdr_set_checksum(hdr, 0x0000);
gre0_hdr_set_offset(hdr, 44);
gre0_hdr_set_key(hdr, 0);
gre0_hdr_set_seq(hdr, 0);
gre0_hdr_set_routing_data(hdr, (const char *)gre0_opt_chek_rout + 8, 52);
EXPECT_TRUE(memcmp(buff, gre0_opt_chek_rout, 60) == 0);
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,66 @@
#include <gtest/gtest.h>
#include "gre1_utils.h"
/*
* Generic Routing Encapsulation (PPP)
* Flags and Version: 0x3081
* 0... .... .... .... = Checksum Bit: No
* .0.. .... .... .... = Routing Bit: No
* ..1. .... .... .... = Key Bit: Yes
* ...1 .... .... .... = Sequence Number Bit: Yes
* .... 0... .... .... = Strict Source Route Bit: No
* .... .000 .... .... = Recursion control: 0
* .... .... 1... .... = Acknowledgment: Yes
* .... .... .000 0... = Flags (Reserved): 0
* .... .... .... .001 = Version: Enhanced GRE (1)
* Protocol Type: PPP (0x880b)
* Payload Length: 103
* Call ID: 6016
* Sequence Number: 430001
* Acknowledgment Number: 539254
*/
unsigned char gre1_opt_seq_ack[] = {
0x30, 0x81, 0x88, 0x0b, 0x00, 0x67, 0x17, 0x80, 0x00, 0x06, 0x8f, 0xb1, 0x00, 0x08, 0x3a, 0x76};
TEST(GRE1_UTILS, GET_1)
{
const struct gre1_hdr *hdr = (struct gre1_hdr *)gre1_opt_seq_ack;
EXPECT_TRUE(gre1_hdr_get_flags(hdr) == 0x3081);
EXPECT_TRUE(gre1_hdr_get_seq_flag(hdr) == 1);
EXPECT_TRUE(gre1_hdr_get_ack_flag(hdr) == 1);
EXPECT_TRUE(gre1_hdr_get_version(hdr) == 1);
EXPECT_TRUE(gre1_hdr_get_proto(hdr) == 0x880b);
EXPECT_TRUE(gre1_hdr_get_payload_length(hdr) == 103);
EXPECT_TRUE(gre1_hdr_get_call_id(hdr) == 6016);
EXPECT_TRUE(gre1_hdr_get_seq(hdr) == 430001);
EXPECT_TRUE(gre1_hdr_get_ack(hdr) == 539254);
EXPECT_TRUE(calc_gre1_hdr_len((const char *)gre1_opt_seq_ack, sizeof(gre1_opt_seq_ack)) == 16);
}
TEST(GRE1_UTILS, SET_1)
{
char buff[16] = {0};
struct gre1_hdr *hdr = (struct gre1_hdr *)buff;
gre1_hdr_set_flags(hdr, 0x3081);
gre1_hdr_set_seq_flag(hdr, 1);
gre1_hdr_set_ack_flag(hdr, 1);
gre1_hdr_set_version(hdr, 1);
gre1_hdr_set_proto(hdr, 0x880b);
gre1_hdr_set_payload_length(hdr, 103);
gre1_hdr_set_call_id(hdr, 6016);
gre1_hdr_set_seq(hdr, 430001);
gre1_hdr_set_ack(hdr, 539254);
EXPECT_TRUE(memcmp(buff, gre1_opt_seq_ack, 16) == 0);
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -1,136 +0,0 @@
#include <gtest/gtest.h>
#include "gre_utils.h"
/*
* Generic Routing Encapsulation (IP)
* Flags and Version: 0x0000
* 0... .... .... .... = Checksum Bit: No
* .0.. .... .... .... = Routing Bit: No
* ..0. .... .... .... = Key Bit: No
* ...0 .... .... .... = Sequence Number Bit: No
* .... 0... .... .... = Strict Source Route Bit: No
* .... .000 .... .... = Recursion control: 0
* .... .... 0000 0... = Flags (Reserved): 0
* .... .... .... .000 = Version: GRE (0)
* Protocol Type: IP (0x0800)
*/
unsigned char ver0_data1[] = {
0x00, 0x00, 0x08, 0x00};
TEST(GREV0_UTILS, NO_OPTION)
{
const struct gre_hdr *hdr = (struct gre_hdr *)ver0_data1;
EXPECT_TRUE(gre_hdr_get_ver(hdr) == 0);
EXPECT_TRUE(gre_hdr_get_proto(hdr) == 0x0800);
EXPECT_TRUE(calc_gre_hdr_len((const char *)ver0_data1, sizeof(ver0_data1)) == 4);
}
/*
* Generic Routing Encapsulation (IP)
* Flags and Version: 0x2000
* 0... .... .... .... = Checksum Bit: No
* .0.. .... .... .... = Routing Bit: No
* ..1. .... .... .... = Key Bit: Yes
* ...0 .... .... .... = Sequence Number Bit: No
* .... 0... .... .... = Strict Source Route Bit: No
* .... .000 .... .... = Recursion control: 0
* .... .... 0000 0... = Flags (Reserved): 0
* .... .... .... .000 = Version: GRE (0)
* Protocol Type: IP (0x0800)
* Key: 0x00000384
*/
unsigned char ver0_data2[] = {0x20, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x84};
TEST(GREV0_UTILS, KEY_OPTION)
{
const struct gre_hdr *hdr = (struct gre_hdr *)ver0_data2;
EXPECT_TRUE(gre_hdr_get_ver(hdr) == 0);
EXPECT_TRUE(gre_hdr_get_proto(hdr) == 0x0800);
EXPECT_TRUE(calc_gre_hdr_len((const char *)ver0_data2, sizeof(ver0_data2)) == 8);
}
/*
* Generic Routing Encapsulation (IP)
* Flags and Version: 0xc000
* 1... .... .... .... = Checksum Bit: Yes
* .1.. .... .... .... = Routing Bit: Yes
* ..0. .... .... .... = Key Bit: No
* ...0 .... .... .... = Sequence Number Bit: No
* .... 0... .... .... = Strict Source Route Bit: No
* .... .000 .... .... = Recursion control: 0
* .... .... 0000 0... = Flags (Reserved): 0
* .... .... .... .000 = Version: GRE (0)
* Protocol Type: IP (0x0800)
* Checksum: 0x0000 incorrect, should be 0xea95
* [Expert Info (Warning/Protocol): Incorrect GRE Checksum [should be 0xea95]]
* [Incorrect GRE Checksum [should be 0xea95]]
* [Severity level: Warning]
* [Group: Protocol]
* [Checksum Status: Bad]
* Offset: 44
* Routing
* Address Family: 2
* SRE Offset: 0
* SRE Length: 44
* Routing Information: 6c696e6b5f696e666f206c696e6b5f696e666f206c696e6b5f696e666f206c696e6b5f696e666f2000000000
* Routing
* Address Family: 0
* SRE Offset: 0
* SRE Length: 0
*/
unsigned char ver0_data3[] = {
0xc0, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x2c, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b,
0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
TEST(GREV0_UTILS, CHECKSUM_ROUTING_OPTION)
{
const struct gre_hdr *hdr = (struct gre_hdr *)ver0_data3;
EXPECT_TRUE(gre_hdr_get_ver(hdr) == 0);
EXPECT_TRUE(gre_hdr_get_proto(hdr) == 0x0800);
EXPECT_TRUE(calc_gre_hdr_len((const char *)ver0_data3, sizeof(ver0_data3)) == 60);
}
/*
* Generic Routing Encapsulation (PPP)
* Flags and Version: 0x3081
* 0... .... .... .... = Checksum Bit: No
* .0.. .... .... .... = Routing Bit: No
* ..1. .... .... .... = Key Bit: Yes
* ...1 .... .... .... = Sequence Number Bit: Yes
* .... 0... .... .... = Strict Source Route Bit: No
* .... .000 .... .... = Recursion control: 0
* .... .... 1... .... = Acknowledgment: Yes
* .... .... .000 0... = Flags (Reserved): 0
* .... .... .... .001 = Version: Enhanced GRE (1)
* Protocol Type: PPP (0x880b)
* Payload Length: 103
* Call ID: 6016
* Sequence Number: 430001
* Acknowledgment Number: 539254
*/
unsigned char ver1_data1[] = {
0x30, 0x81, 0x88, 0x0b, 0x00, 0x67, 0x17, 0x80, 0x00, 0x06, 0x8f, 0xb1, 0x00, 0x08, 0x3a, 0x76};
TEST(GREV1_UTILS, SEQ_ACK_OPTION)
{
const struct gre_hdr *hdr = (struct gre_hdr *)ver1_data1;
EXPECT_TRUE(gre_hdr_get_ver(hdr) == 1);
EXPECT_TRUE(gre_hdr_get_proto(hdr) == 0x880b);
EXPECT_TRUE(calc_gre_hdr_len((const char *)ver1_data1, sizeof(ver1_data1)) == 16);
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -5,8 +5,7 @@
#include "udp_utils.h" #include "udp_utils.h"
#include "ip4_utils.h" #include "ip4_utils.h"
#include "ip6_utils.h" #include "ip6_utils.h"
#include "gtp1_utils.h" #include "gtp_utils.h"
#include "gtp2_utils.h"
#include "packet_def.h" #include "packet_def.h"
#include "packet_dump.h" #include "packet_dump.h"
#include "packet_layer.h" #include "packet_layer.h"
@@ -550,12 +549,12 @@ TEST(PACKET_BUILD_TCP, ETH_IP6_UDP_GTP_IP4_TCP)
{ {
continue; continue;
} }
if ((38 <= i && i <= 39) || // skip UDP length if ((58 <= i && i <= 59) || // skip UDP length
(40 <= i && i <= 41)) // skip UDP checksum (60 <= i && i <= 61)) // skip UDP checksum
{ {
continue; continue;
} }
if ((44 <= i && i <= 45)) // skip gtp length if ((64 <= i && i <= 65)) // skip gtp length
{ {
continue; continue;
} }