This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
stellar-stellar/src/packet/packet.cpp

1565 lines
48 KiB
C++
Raw Normal View History

2023-12-15 18:57:13 +08:00
#include <string.h>
#include <stdlib.h>
#include <netinet/icmp6.h>
#include <netinet/ip_icmp.h>
2023-12-15 18:57:13 +08:00
#include <linux/ppp_defs.h>
#include "uthash.h"
#include "packet_priv.h"
2024-06-05 16:44:32 +08:00
#include "eth_utils.h"
#include "gre_utils.h"
2024-02-21 11:14:21 +08:00
#include "udp_utils.h"
2024-02-21 11:49:20 +08:00
#include "tcp_utils.h"
2024-02-21 14:34:34 +08:00
#include "ipv4_utils.h"
2024-02-21 15:06:48 +08:00
#include "ipv6_utils.h"
#include "mpls_utils.h"
2024-06-07 14:47:38 +08:00
#include "l2tp_utils.h"
2024-06-05 11:41:46 +08:00
#include "vlan_utils.h"
2024-06-05 14:36:04 +08:00
#include "vxlan_utils.h"
2023-12-15 18:57:13 +08:00
#define likely(expr) __builtin_expect((expr), 1)
#define unlikely(expr) __builtin_expect((expr), 0)
#define PACKET_LOG_DATA_INSUFFICIENCY(pkt, layer) \
{ \
PACKET_LOG_WARN("pkt: %p, layer: %s, data insufficiency", \
2024-06-12 18:21:45 +08:00
(pkt), layer_proto_to_str(layer)); \
2023-12-15 18:57:13 +08:00
}
2024-06-12 18:21:45 +08:00
#define PACKET_LOG_UNSUPPORT_PROTO(pkt, layer, next_proto) \
{ \
PACKET_LOG_WARN("pkt: %p, layer: %s, unsupport next proto %d", \
(pkt), layer_proto_to_str(layer), (next_proto)); \
2023-12-15 18:57:13 +08:00
}
#define PACKET_LOG_UNSUPPORT_ETHPROTO(pkt, next_proto) \
{ \
PACKET_LOG_WARN("pkt: %p, layer: l3, unsupport next eth proto %s", \
(pkt), eth_proto_to_str(next_proto)); \
2023-12-15 18:57:13 +08:00
}
#define PACKET_LOG_UNSUPPORT_IPPROTO(pkt, next_proto) \
{ \
PACKET_LOG_WARN("pkt: %p, layer: l4, unsupport next ip proto %s", \
(pkt), ip_proto_to_str(next_proto)); \
2023-12-15 18:57:13 +08:00
}
/******************************************************************************
* Static API
******************************************************************************/
2024-03-08 13:43:03 +08:00
static inline const char *ldbc_method_to_str(enum ldbc_method method);
2024-06-12 18:21:45 +08:00
static inline const char *layer_proto_to_str(enum layer_proto type);
2023-12-15 18:57:13 +08:00
2024-06-12 18:21:45 +08:00
static inline void set_tuple2(const char *data, enum layer_proto type, struct tuple2 *tuple);
static inline void set_tuple4(const char *data, enum layer_proto type, struct tuple4 *tuple);
static inline void set_tuple6(const char *data, enum layer_proto type, struct tuple6 *tuple, uint64_t domain);
2023-12-15 18:57:13 +08:00
static inline struct raw_layer *get_free_layer(struct packet *pkt);
2023-12-15 18:57:13 +08:00
static inline uint16_t get_gtp_hdr_len(const char *data, uint16_t len);
// 数据链路层
static inline const char *parse_ether(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_pweth(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_ppp(struct packet *pkt, const char *data, uint16_t len);
2024-06-07 14:47:38 +08:00
static inline const char *parse_l2tpv2_over_udp(struct packet *pkt, const char *data, uint16_t len);
2024-05-24 16:14:20 +08:00
static inline const char *parse_l2tpv3_over_udp(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_l2tpv3_over_ip(struct packet *pkt, const char *data, uint16_t len);
2023-12-15 18:57:13 +08:00
// 数据链路层 -- 隧道
static inline const char *parse_vlan(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_pppoe_ses(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_mpls(struct packet *pkt, const char *data, uint16_t len);
2023-12-15 18:57:13 +08:00
// 网络层
static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_auth(struct packet *pkt, const char *data, uint16_t len);
2023-12-15 18:57:13 +08:00
// 网络层 -- 隧道
static inline const char *parse_gre(struct packet *pkt, const char *data, uint16_t len);
2023-12-15 18:57:13 +08:00
// 传输层
static inline const char *parse_udp(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_tcp(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_icmp(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_icmp6(struct packet *pkt, const char *data, uint16_t len);
2023-12-15 18:57:13 +08:00
// 传输层 -- 隧道
static inline const char *parse_vxlan(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_gtpv1_u(struct packet *pkt, const char *data, uint16_t len);
2023-12-15 18:57:13 +08:00
// L3/L4
static inline const char *parse_l3(struct packet *pkt, uint16_t next_proto, const char *data, uint16_t len);
static inline const char *parse_l4(struct packet *pkt, uint8_t next_proto, const char *data, uint16_t len);
2023-12-15 18:57:13 +08:00
/******************************************************************************
* Private API -- Utils
******************************************************************************/
2024-03-08 13:43:03 +08:00
static inline const char *ldbc_method_to_str(enum ldbc_method method)
2023-12-15 18:57:13 +08:00
{
switch (method)
{
case LDBC_METHOD_HASH_INT_IP:
return "outter_internal_ip";
case LDBC_METHOD_HASH_EXT_IP:
return "outter_external_ip";
case LDBC_METHOD_HASH_INT_IP_AND_EXT_IP:
return "outter_internal_ip_and_external_ip";
case LDBC_METHOD_HASH_INNERMOST_INT_IP:
return "inner_internal_ip";
case LDBC_METHOD_HASH_INNERMOST_EXT_IP:
return "inner_external_ip";
default:
return "unknown";
}
}
2024-06-12 18:21:45 +08:00
static inline const char *layer_proto_to_str(enum layer_proto type)
2023-12-15 18:57:13 +08:00
{
switch (type)
{
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_ETHER:
2023-12-15 18:57:13 +08:00
return "ETH";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_PWETH:
return "PWETH";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_PPP:
2023-12-15 18:57:13 +08:00
return "PPP";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_L2TP:
2024-05-24 16:14:20 +08:00
return "L2TP";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_VLAN:
2023-12-15 18:57:13 +08:00
return "VLAN";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_PPPOE:
2023-12-15 18:57:13 +08:00
return "PPPOE";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_MPLS:
2023-12-15 18:57:13 +08:00
return "MPLS";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_IPV4:
2023-12-15 18:57:13 +08:00
return "IPV4";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_IPV6:
2023-12-15 18:57:13 +08:00
return "IPV6";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_IPAH:
return "IPAH";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_GRE:
2023-12-15 18:57:13 +08:00
return "GRE";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_UDP:
2023-12-15 18:57:13 +08:00
return "UDP";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_TCP:
2023-12-15 18:57:13 +08:00
return "TCP";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_ICMP:
2024-05-24 16:14:20 +08:00
return "ICMP";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_ICMP6:
2024-05-24 16:14:20 +08:00
return "ICMP6";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_VXLAN:
2023-12-15 18:57:13 +08:00
return "VXLAN";
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_GTPV1_U:
2023-12-15 18:57:13 +08:00
return "GTPV1";
default:
return "UNKNOWN";
}
}
2024-06-12 18:21:45 +08:00
static inline void set_tuple2(const char *data, enum layer_proto type, struct tuple2 *tuple)
2023-12-15 18:57:13 +08:00
{
const struct ip *ipv4 = NULL;
const struct ip6_hdr *ipv6 = NULL;
switch (type)
{
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_IPV4:
2023-12-15 18:57:13 +08:00
ipv4 = (const struct ip *)data;
tuple->ip_type = IP_TYPE_V4;
tuple->src_addr.v4.s_addr = ipv4->ip_src.s_addr;
tuple->dst_addr.v4.s_addr = ipv4->ip_dst.s_addr;
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_IPV6:
2023-12-15 18:57:13 +08:00
ipv6 = (const struct ip6_hdr *)data;
tuple->ip_type = IP_TYPE_V6;
tuple->src_addr.v6 = ipv6->ip6_src;
tuple->dst_addr.v6 = ipv6->ip6_dst;
break;
default:
break;
}
}
2024-06-12 18:21:45 +08:00
static inline void set_tuple4(const char *data, enum layer_proto type, struct tuple4 *tuple)
2023-12-15 18:57:13 +08:00
{
const struct ip *ipv4 = NULL;
const struct ip6_hdr *ipv6 = NULL;
const struct tcphdr *tcp = NULL;
const struct udphdr *udp = NULL;
switch (type)
{
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_TCP:
2023-12-15 18:57:13 +08:00
tcp = (const struct tcphdr *)data;
tuple->src_port = tcp->th_sport;
tuple->dst_port = tcp->th_dport;
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_UDP:
2023-12-15 18:57:13 +08:00
udp = (const struct udphdr *)data;
tuple->src_port = udp->uh_sport;
tuple->dst_port = udp->uh_dport;
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_IPV4:
2023-12-15 18:57:13 +08:00
ipv4 = (const struct ip *)data;
tuple->ip_type = IP_TYPE_V4;
tuple->src_addr.v4.s_addr = ipv4->ip_src.s_addr;
tuple->dst_addr.v4.s_addr = ipv4->ip_dst.s_addr;
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_IPV6:
2023-12-15 18:57:13 +08:00
ipv6 = (const struct ip6_hdr *)data;
tuple->ip_type = IP_TYPE_V6;
tuple->src_addr.v6 = ipv6->ip6_src;
tuple->dst_addr.v6 = ipv6->ip6_dst;
break;
default:
break;
}
}
2024-06-12 18:21:45 +08:00
static inline void set_tuple6(const char *data, enum layer_proto type, struct tuple6 *tuple, uint64_t domain)
2023-12-15 18:57:13 +08:00
{
const struct ip *ipv4 = NULL;
const struct ip6_hdr *ipv6 = NULL;
const struct tcphdr *tcp = NULL;
const struct udphdr *udp = NULL;
2024-01-15 14:31:38 +08:00
tuple->domain = domain;
2023-12-15 18:57:13 +08:00
switch (type)
{
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_TCP:
2023-12-15 18:57:13 +08:00
tcp = (const struct tcphdr *)data;
tuple->ip_proto = IPPROTO_TCP;
tuple->src_port = tcp->th_sport;
tuple->dst_port = tcp->th_dport;
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_UDP:
2023-12-15 18:57:13 +08:00
udp = (const struct udphdr *)data;
tuple->ip_proto = IPPROTO_UDP;
tuple->src_port = udp->uh_sport;
tuple->dst_port = udp->uh_dport;
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_IPV4:
2023-12-15 18:57:13 +08:00
ipv4 = (const struct ip *)data;
tuple->ip_type = IP_TYPE_V4;
tuple->src_addr.v4.s_addr = ipv4->ip_src.s_addr;
tuple->dst_addr.v4.s_addr = ipv4->ip_dst.s_addr;
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_IPV6:
2023-12-15 18:57:13 +08:00
ipv6 = (const struct ip6_hdr *)data;
tuple->ip_type = IP_TYPE_V6;
tuple->src_addr.v6 = ipv6->ip6_src;
tuple->dst_addr.v6 = ipv6->ip6_dst;
break;
default:
break;
}
}
static inline struct raw_layer *get_free_layer(struct packet *pkt)
2023-12-15 18:57:13 +08:00
{
if (pkt->layers_used >= pkt->layers_size)
2023-12-15 18:57:13 +08:00
{
return NULL;
}
return &pkt->layers[pkt->layers_used];
2023-12-15 18:57:13 +08:00
}
#define SET_LAYER(_pkt, _layer, _type, _hdr_len, _data, _len, _trim) \
2023-12-18 16:51:17 +08:00
{ \
(_layer)->type = (_type); \
(_layer)->hdr_offset = (_pkt)->data_len - (_pkt)->trim_len - (_len); \
2023-12-18 16:51:17 +08:00
(_layer)->hdr_ptr = (_data); \
(_layer)->hdr_len = (_hdr_len); \
(_layer)->pld_ptr = (_data) + (_hdr_len); \
(_layer)->pld_len = (_len) - (_hdr_len) - (_trim); \
(_pkt)->trim_len += (_trim); \
(_pkt)->layers_used++; \
2023-12-19 10:47:26 +08:00
PACKET_LOG_DEBUG("layer[%d/%d]: %s, hdr_offset: %d, hdr_ptr: %p, hdr_len: %d, pld_ptr: %p, pld_len: %d", \
2024-06-12 18:21:45 +08:00
(_pkt)->layers_used - 1, (_pkt)->layers_size, layer_proto_to_str((_type)), \
2023-12-18 16:51:17 +08:00
(_layer)->hdr_offset, (_layer)->hdr_ptr, (_layer)->hdr_len, (_layer)->pld_ptr, (_layer)->pld_len); \
2023-12-15 18:57:13 +08:00
}
/******************************************************************************
* Private API -- Parses
******************************************************************************/
static inline uint16_t get_gtp_hdr_len(const char *data, uint16_t len)
{
#define GTP_HDR_VER (0xE0)
#define GTP_HDR_FLAG_N_PDU (0x01)
#define GTP_HDR_FLAG_SEQ_NUM (0x02)
#define GTP_HDR_FLAG_EXT_HDR (0x04)
struct gtp_hdr
{
uint8_t flags;
uint8_t msg_type;
uint16_t msg_len;
uint32_t teid;
} __attribute__((__packed__));
struct gtp_opt
{
uint16_t seq_num;
uint8_t npdu;
uint8_t next_ext_hdr;
} __attribute__((__packed__));
uint16_t hdr_offset = 0;
if (len < sizeof(struct gtp_hdr))
{
return 0;
}
const struct gtp_hdr *gtp = (const struct gtp_hdr *)data;
hdr_offset += sizeof(struct gtp_hdr); // skip gre hdr
// GTPv0 Not Supported
if (((gtp->flags & GTP_HDR_VER) >> 5) != 1)
{
return 0;
}
if (gtp->flags & (GTP_HDR_FLAG_SEQ_NUM | GTP_HDR_FLAG_N_PDU | GTP_HDR_FLAG_EXT_HDR))
{
if (hdr_offset + sizeof(struct gtp_opt) > len)
{
return 0;
}
struct gtp_opt *opt_hdr = (struct gtp_opt *)((char *)data + hdr_offset);
uint8_t next_ext_hdr = opt_hdr->next_ext_hdr;
hdr_offset += sizeof(struct gtp_opt); // skip gre opt
while (next_ext_hdr)
{
if (hdr_offset + 1 > len)
{
return 0;
}
uint8_t length = *((char *)data + hdr_offset) * 4 - 2;
hdr_offset += 1; // skip length field
if (hdr_offset + length + 1 > len)
{
return 0;
}
hdr_offset += length; // skip data field
next_ext_hdr = *((char *)data + hdr_offset);
hdr_offset += 1; // skip next ext hdr field
}
}
return hdr_offset;
}
static inline const char *parse_ether(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
if (unlikely(len < sizeof(struct ethhdr)))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_ETHER);
2023-12-15 18:57:13 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2023-12-15 18:57:13 +08:00
if (unlikely(layer == NULL))
{
return data;
}
uint16_t next_proto = eth_hdr_get_proto((const struct ethhdr *)data);
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_ETHER, sizeof(struct ethhdr), data, len, 0);
2023-12-15 18:57:13 +08:00
return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
}
static inline const char *parse_pweth(struct packet *pkt, const char *data, uint16_t len)
{
/*
* PW Ethernet Control Word
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |0 0 0 0| Reserved | Sequence Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* Reference: https://tools.ietf.org/html/rfc4448
*/
if (unlikely(len < 4))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_PWETH);
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
if (unlikely(layer == NULL))
{
return data;
}
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_PWETH, 4, data, len, 0);
return parse_ether(pkt, layer->pld_ptr, layer->pld_len);
}
static inline int is_ppp_proto(uint16_t proto)
{
// /usr/include/linux/ppp_defs.h.html
switch (proto)
{
case PPP_IP: /* Internet Protocol */
case PPP_AT: /* AppleTalk Protocol */
case PPP_IPX: /* IPX protocol */
case PPP_VJC_COMP: /* VJ compressed TCP */
case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */
case PPP_MP: /* Multilink protocol */
case PPP_IPV6: /* Internet Protocol Version 6 */
case PPP_COMPFRAG: /* fragment compressed below bundle */
case PPP_COMP: /* compressed packet */
case PPP_MPLS_UC: /* Multi Protocol Label Switching - Unicast */
case PPP_MPLS_MC: /* Multi Protocol Label Switching - Multicast */
case PPP_IPCP: /* IP Control Protocol */
case PPP_ATCP: /* AppleTalk Control Protocol */
case PPP_IPXCP: /* IPX Control Protocol */
case PPP_IPV6CP: /* IPv6 Control Protocol */
case PPP_CCPFRAG: /* CCP at link level (below MP bundle) */
// case PPP_CCP: /* Compression Control Protocol */ (same as PPP_CCPFRAG)
case PPP_MPLSCP: /* MPLS Control Protocol */
case PPP_LCP: /* Link Control Protocol */
case PPP_PAP: /* Password Authentication Protocol */
case PPP_LQR: /* Link Quality Report protocol */
case PPP_CHAP: /* Cryptographic Handshake Auth. Protocol */
case PPP_CBCP: /* Callback Control Protocol */
return 1;
default:
return 0;
}
}
static inline const char *parse_ppp(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
/*
* https://datatracker.ietf.org/doc/html/rfc1661#section-2
* +----------+-------------+---------+
* | Protocol | Information | Padding |
* | 8/16 bits| * | * |
* +----------+-------------+---------+
*
* https://datatracker.ietf.org/doc/html/rfc1331#section-3.1
* +----------+----------+----------+----------+------------
* | Flag | Address | Control | Protocol | Information
* | 01111110 | 11111111 | 00000011 | 16 bits | *
* +----------+----------+----------+----------+------------
* ---+----------+----------+-----------------
* | FCS | Flag | Inter-frame Fill
* | 16 bits | 01111110 | or next Address
* ---+----------+----------+-----------------
*/
2023-12-15 18:57:13 +08:00
if (unlikely(len < 4))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_PPP);
2023-12-15 18:57:13 +08:00
return data;
}
uint16_t hdr_len = 0;
uint16_t next_proto = 0;
// ppp header 1 byte
next_proto = *((uint8_t *)data);
if (is_ppp_proto(next_proto))
{
hdr_len = 1;
goto success;
}
// ppp header 2 bytes
next_proto = ntohs(*((uint16_t *)data));
if (is_ppp_proto(next_proto))
{
hdr_len = 2;
goto success;
}
// ppp header 4 bytes
next_proto = ntohs(*((uint16_t *)data + 1));
hdr_len = 4;
success:
struct raw_layer *layer = get_free_layer(pkt);
2023-12-15 18:57:13 +08:00
if (unlikely(layer == NULL))
{
return data;
}
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_PPP, hdr_len, data, len, 0);
2023-12-15 18:57:13 +08:00
switch (next_proto)
{
case PPP_IP:
return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
case PPP_IPV6:
return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
default:
2024-06-12 18:21:45 +08:00
PACKET_LOG_UNSUPPORT_PROTO(pkt, LAYER_PROTO_PPP, next_proto);
2023-12-15 18:57:13 +08:00
return layer->pld_ptr;
}
}
2024-06-07 14:47:38 +08:00
static inline const char *parse_l2tpv2_over_udp(struct packet *pkt, const char *data, uint16_t len)
2024-05-24 16:14:20 +08:00
{
2024-06-07 14:47:38 +08:00
uint16_t hdr_len = calc_udp_l2tpv2_hdr_len(data, len);
2024-05-24 16:14:20 +08:00
if (unlikely(hdr_len == 0 || hdr_len > len))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_L2TP);
2024-05-24 16:14:20 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2024-05-24 16:14:20 +08:00
if (unlikely(layer == NULL))
{
return data;
}
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_L2TP, hdr_len, data, len, 0);
2024-05-24 16:14:20 +08:00
2024-06-07 14:47:38 +08:00
// control message
if (l2tp_hdr_get_type((const struct l2tp_hdr *)data))
2024-05-24 16:14:20 +08:00
{
return layer->pld_ptr;
}
2024-06-07 14:47:38 +08:00
// data message
2024-05-24 16:14:20 +08:00
else
{
return parse_ppp(pkt, layer->pld_ptr, layer->pld_len);
}
}
static inline const char *parse_l2tpv3_over_udp(struct packet *pkt, const char *data, uint16_t len)
{
2024-06-07 14:47:38 +08:00
uint16_t hdr_len = calc_udp_l2tpv3_hdr_len(data, len);
if (unlikely(hdr_len == 0 || hdr_len > len))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_L2TP);
2024-06-07 14:47:38 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2024-06-07 14:47:38 +08:00
if (unlikely(layer == NULL))
{
return data;
}
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_L2TP, hdr_len, data, len, 0);
2024-06-07 14:47:38 +08:00
// control message
if (l2tp_hdr_get_type((const struct l2tp_hdr *)data))
{
return layer->pld_ptr;
}
// data message
else
{
// TOOD
return layer->pld_ptr;
}
2024-05-24 16:14:20 +08:00
}
static inline const char *parse_l2tpv3_over_ip(struct packet *pkt, const char *data, uint16_t len)
{
2024-06-07 14:47:38 +08:00
uint16_t hdr_len = calc_ip_l2tpv3_hdr_len(data, len);
if (unlikely(hdr_len == 0 || hdr_len > len))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_L2TP);
2024-06-07 14:47:38 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2024-06-07 14:47:38 +08:00
if (unlikely(layer == NULL))
{
return data;
}
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_L2TP, hdr_len, data, len, 0);
2024-06-07 14:47:38 +08:00
// data message
if (ntohl(*((uint32_t *)data)))
{
// TOOD
return layer->pld_ptr;
}
// control message
else
{
return layer->pld_ptr;
}
2024-05-24 16:14:20 +08:00
}
static inline const char *parse_vlan(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
if (unlikely(len < sizeof(struct vlan_hdr)))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_VLAN);
2023-12-15 18:57:13 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2023-12-15 18:57:13 +08:00
if (unlikely(layer == NULL))
{
return data;
}
2024-06-05 11:41:46 +08:00
uint16_t next_proto = vlan_hdr_get_ethertype((const struct vlan_hdr *)data);
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_VLAN, sizeof(struct vlan_hdr), data, len, 0);
2023-12-15 18:57:13 +08:00
return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
}
static inline const char *parse_pppoe_ses(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
if (unlikely(len < 6))
2023-12-15 18:57:13 +08:00
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_PPPOE);
2023-12-15 18:57:13 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2023-12-15 18:57:13 +08:00
if (unlikely(layer == NULL))
{
return data;
}
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_PPPOE, 6, data, len, 0);
2023-12-15 18:57:13 +08:00
return parse_ppp(pkt, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
}
static inline const char *parse_mpls(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
if (unlikely(len < 4))
2023-12-15 18:57:13 +08:00
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_MPLS);
2023-12-15 18:57:13 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2023-12-15 18:57:13 +08:00
if (unlikely(layer == NULL))
{
return data;
}
2024-06-05 10:39:57 +08:00
if (mpls_label_get_bos((const struct mpls_label *)data))
2023-12-15 18:57:13 +08:00
{
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_MPLS, 4, data, len, 0);
if (layer->pld_len == 0)
{
return layer->pld_ptr;
}
uint8_t next_proto = layer->pld_ptr[0] >> 4;
switch (next_proto)
2023-12-15 18:57:13 +08:00
{
case 0:
// the first four digits of the PW Ethernet control word must be "00000", but the first four digits of Ethernet may also be "0000"
if (layer->pld_len >= sizeof(struct ethhdr) && is_eth_proto(eth_hdr_get_proto((const struct ethhdr *)layer->pld_ptr)))
{
return parse_ether(pkt, layer->pld_ptr, layer->pld_len);
}
else
{
return parse_pweth(pkt, layer->pld_ptr, layer->pld_len);
}
2023-12-15 18:57:13 +08:00
case 4:
return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
case 6:
return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
default:
return parse_ether(pkt, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
}
}
else
{
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_MPLS, 4, data, len, 0);
return parse_mpls(pkt, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
}
}
static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
if (unlikely(len < sizeof(struct ip)))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV4);
2023-12-15 18:57:13 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2023-12-15 18:57:13 +08:00
if (unlikely(layer == NULL))
{
return data;
}
const struct ip *hdr = (const struct ip *)data;
2024-02-21 14:34:34 +08:00
uint16_t hdr_len = ipv4_hdr_get_hdr_len(hdr);
2024-03-27 17:11:38 +08:00
if (unlikely(hdr_len > len))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV4);
2024-03-27 17:11:38 +08:00
return data;
}
uint16_t total_len = ipv4_hdr_get_total_len(hdr);
if (unlikely(total_len > len))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV4);
return data;
}
if (unlikely(total_len < hdr_len))
{
PACKET_LOG_ERROR("packet %p ip total_len %d < hdr_len %d", pkt, total_len, hdr_len);
return data;
}
uint16_t trim_len = len - total_len;
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_IPV4, hdr_len, data, len, trim_len);
2023-12-15 18:57:13 +08:00
2023-12-18 16:51:17 +08:00
// ip fragmented
2024-02-22 18:52:04 +08:00
if (ipv4_hdr_get_mf_flag(hdr) || ipv4_hdr_get_frag_offset(hdr))
2023-12-18 16:51:17 +08:00
{
2024-05-29 17:55:44 +08:00
PACKET_LOG_WARN("packet %p ip layer %p is fragmented", pkt, layer);
pkt->frag_layer = layer;
return layer->pld_ptr;
2023-12-18 16:51:17 +08:00
}
uint8_t next_proto = ipv4_hdr_get_proto(hdr);
return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
}
static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
/*
* IP6 Extension Headers
*
* Internet Protocol, Version 6 (IPv6) : https://datatracker.ietf.org/doc/html/rfc2460
* IP Encapsulating Security Payload (ESP) : https://datatracker.ietf.org/doc/html/rfc2406
* IP Authentication Header : https://datatracker.ietf.org/doc/html/rfc4302
*
* skip next header
* #define IPPROTO_HOPOPTS 0 // IP6 hop-by-hop options
* #define IPPROTO_ROUTING 43 // IP6 routing header
* #define IPPROTO_AH 51 // IP6 Auth Header
* #define IPPROTO_DSTOPTS 60 // IP6 destination option
*
* not skip next header
* #define IPPROTO_FRAGMENT 44 // IP6 fragmentation header
* #define IPPROTO_ESP 50 // IP6 Encap Sec. Payload
* #define IPPROTO_NONE 59 // IP6 no next header
*/
2023-12-15 18:57:13 +08:00
if (unlikely(len < sizeof(struct ip6_hdr)))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV6);
2023-12-15 18:57:13 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2023-12-15 18:57:13 +08:00
if (unlikely(layer == NULL))
{
return data;
}
const struct ip6_hdr *hdr = (const struct ip6_hdr *)data;
uint16_t pld_len = ipv6_hdr_get_payload_len(hdr);
if (unlikely(pld_len + sizeof(struct ip6_hdr) > len))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV6);
return data;
}
uint8_t next_proto = ipv6_hdr_get_next_header(hdr);
uint16_t hdr_len = sizeof(struct ip6_hdr);
uint16_t trim_len = len - pld_len - sizeof(struct ip6_hdr);
const char *next_hdr_ptr = data + hdr_len;
while (next_proto == IPPROTO_HOPOPTS || next_proto == IPPROTO_ROUTING || next_proto == IPPROTO_AH || next_proto == IPPROTO_DSTOPTS)
{
if (unlikely(pld_len < 2))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV6);
return data;
}
struct ip6_ext *ext = (struct ip6_ext *)next_hdr_ptr;
uint16_t skip_len = 0;
if (next_proto == IPPROTO_AH)
{
/*
* https://datatracker.ietf.org/doc/html/rfc4302#section-2
* For IPv6, the total length of the header must be a multiple of 8-octet units.
* (Note that although IPv6 [DH98] characterizes AH as an extension header,
* its length is measured in 32-bit words, not the 64-bit words used by other IPv6 extension headers.)
*/
skip_len = ext->ip6e_len * 4 + 8;
}
else
{
skip_len = ext->ip6e_len * 8 + 8;
}
if (unlikely(skip_len > pld_len))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV6);
return data;
}
hdr_len += skip_len;
pld_len -= skip_len;
next_hdr_ptr += skip_len;
next_proto = ext->ip6e_nxt;
}
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_IPV6, hdr_len, data, len, trim_len);
2023-12-15 18:57:13 +08:00
2024-02-22 18:52:04 +08:00
// ipv6 fragment
if (next_proto == IPPROTO_FRAGMENT)
{
2024-05-29 17:55:44 +08:00
PACKET_LOG_WARN("packet %p ipv6 layer %p is fragmented", pkt, layer);
pkt->frag_layer = layer;
return layer->pld_ptr;
2024-02-22 18:52:04 +08:00
}
2024-02-21 11:14:21 +08:00
return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
}
static inline const char *parse_auth(struct packet *pkt, const char *data, uint16_t len)
{
/*
* https://datatracker.ietf.org/doc/html/rfc4302#section-2
* For IPv4: AH not IPv4 option, as an single layer
* For IPv6: AH as IPv6 extension header
*
* AH Format
*
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Next Header | Payload Len | RESERVED |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Security Parameters Index (SPI) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sequence Number Field |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* + Integrity Check Value-ICV (variable) |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
if (unlikely(len < 12))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPAH);
return data;
}
/*
* https://datatracker.ietf.org/doc/html/rfc4302#section-2
* For IPv4, This 8-bit field specifies the length of AH in 32-bit words (4-byte units), minus "2".
* Thus, for example, if an integrity algorithm yields a 96-bit authentication value,
* this length field will be "4" (3 32-bit word fixed fields plus 3 32-bit words for the ICV, minus 2).
*/
uint8_t next_proto = ((const uint8_t *)data)[0];
uint16_t hdr_len = ((const uint8_t *)data)[1] * 4 + 8;
if (unlikely(len < hdr_len))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPAH);
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
if (unlikely(layer == NULL))
{
return data;
}
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_IPAH, hdr_len, data, len, 0);
return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len);
}
static inline const char *parse_gre(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
2024-06-05 16:44:32 +08:00
uint16_t hdr_len = calc_gre_hdr_len(data, len);
2024-03-27 17:11:38 +08:00
if (unlikely(hdr_len == 0 || hdr_len > len))
2023-12-15 18:57:13 +08:00
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_GRE);
2023-12-15 18:57:13 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2023-12-15 18:57:13 +08:00
if (unlikely(layer == NULL))
{
return data;
}
2024-06-05 16:44:32 +08:00
uint16_t next_proto = gre_hdr_get_proto((const struct gre_hdr *)data);
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_GRE, hdr_len, data, len, 0);
2023-12-15 18:57:13 +08:00
2024-06-05 16:44:32 +08:00
return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
}
static inline const char *parse_udp(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
if (unlikely(len < sizeof(struct udphdr)))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_UDP);
2023-12-15 18:57:13 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2023-12-15 18:57:13 +08:00
if (unlikely(layer == NULL))
{
return data;
}
const struct udphdr *hdr = (struct udphdr *)data;
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_UDP, sizeof(struct udphdr), data, len, 0);
2023-12-15 18:57:13 +08:00
uint16_t src_port = udp_hdr_get_src_port(hdr);
uint16_t dst_port = udp_hdr_get_dst_port(hdr);
if (dst_port == 4789)
2023-12-15 18:57:13 +08:00
{
2024-03-21 10:06:11 +08:00
// VXLAN_DPORT 4789
return parse_vxlan(pkt, layer->pld_ptr, layer->pld_len);
2024-03-21 10:06:11 +08:00
}
if (dst_port == 2152 || src_port == 2152)
2024-03-21 10:06:11 +08:00
{
// TODO
// check V1 or V2
2024-03-21 10:06:11 +08:00
// GTP1U_PORT 2152
return parse_gtpv1_u(pkt, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
}
2024-03-21 10:06:11 +08:00
if (dst_port == 2123 || src_port == 2123)
{
// TODO
// GTP-C - GTP control 2123
}
if (dst_port == 1701 || src_port == 1701)
2024-05-24 16:14:20 +08:00
{
// L2TP_DPORT 1701
if (unlikely(layer->pld_len < 8))
{
return layer->pld_ptr;
}
2024-06-07 14:47:38 +08:00
switch (l2tp_hdr_get_ver((const struct l2tp_hdr *)layer->pld_ptr))
2024-05-24 16:14:20 +08:00
{
case 2:
2024-06-07 14:47:38 +08:00
return parse_l2tpv2_over_udp(pkt, layer->pld_ptr, layer->pld_len);
2024-05-24 16:14:20 +08:00
case 3:
return parse_l2tpv3_over_udp(pkt, layer->pld_ptr, layer->pld_len);
default:
return layer->pld_ptr;
}
}
if (dst_port == 3544 || src_port == 3544)
{
// Teredo IPv6 tunneling 3544
if (unlikely(layer->pld_len < sizeof(struct ip6_hdr)))
{
return layer->pld_ptr;
}
const struct ip6_hdr *hdr = (const struct ip6_hdr *)layer->pld_ptr;
if (ipv6_hdr_get_version(hdr) != 6)
{
return layer->pld_ptr;
}
return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len);
}
2024-03-21 10:06:11 +08:00
return layer->pld_ptr;
2023-12-15 18:57:13 +08:00
}
static inline const char *parse_tcp(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
if (unlikely(len < sizeof(struct tcphdr)))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_TCP);
2023-12-15 18:57:13 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2023-12-15 18:57:13 +08:00
if (unlikely(layer == NULL))
{
return data;
}
uint16_t hdr_len = tcp_hdr_get_hdr_len((const struct tcphdr *)data);
2024-03-27 17:11:38 +08:00
if (unlikely(hdr_len > len))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_TCP);
2024-03-27 17:11:38 +08:00
return data;
}
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_TCP, hdr_len, data, len, 0);
2023-12-15 18:57:13 +08:00
return layer->pld_ptr;
}
static inline const char *parse_icmp(struct packet *pkt, const char *data, uint16_t len)
{
if (unlikely(len < sizeof(struct icmphdr)))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_ICMP);
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
if (unlikely(layer == NULL))
{
return data;
}
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_ICMP, sizeof(struct icmphdr), data, len, 0);
return layer->pld_ptr;
}
static inline const char *parse_icmp6(struct packet *pkt, const char *data, uint16_t len)
{
if (unlikely(len < sizeof(struct icmp6_hdr)))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_ICMP6);
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
if (unlikely(layer == NULL))
{
return data;
}
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_ICMP6, sizeof(struct icmp6_hdr), data, len, 0);
return layer->pld_ptr;
}
static inline const char *parse_vxlan(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
if (unlikely(len < sizeof(struct vxlan_hdr)))
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_VXLAN);
2023-12-15 18:57:13 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2023-12-15 18:57:13 +08:00
if (unlikely(layer == NULL))
{
return data;
}
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_VXLAN, sizeof(struct vxlan_hdr), data, len, 0);
2023-12-15 18:57:13 +08:00
return parse_ether(pkt, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
}
static inline const char *parse_gtpv1_u(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
uint16_t hdr_len = get_gtp_hdr_len(data, len);
2024-03-27 17:11:38 +08:00
if (unlikely(hdr_len == 0 || hdr_len > len))
2023-12-15 18:57:13 +08:00
{
2024-06-12 18:21:45 +08:00
PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_GTPV1_U);
2023-12-15 18:57:13 +08:00
return data;
}
struct raw_layer *layer = get_free_layer(pkt);
2023-12-15 18:57:13 +08:00
if (unlikely(layer == NULL))
{
return data;
}
uint8_t next_proto = (((const uint8_t *)(data + hdr_len))[0]) >> 4;
2024-06-12 18:21:45 +08:00
SET_LAYER(pkt, layer, LAYER_PROTO_GTPV1_U, hdr_len, data, len, 0);
2023-12-15 18:57:13 +08:00
switch (next_proto)
{
case 4:
return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
case 6:
return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len);
2023-12-15 18:57:13 +08:00
default:
2024-06-12 18:21:45 +08:00
PACKET_LOG_UNSUPPORT_PROTO(pkt, LAYER_PROTO_GTPV1_U, next_proto);
2023-12-15 18:57:13 +08:00
return layer->pld_ptr;
}
}
static inline const char *parse_l3(struct packet *pkt, uint16_t next_proto, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
switch (next_proto)
{
case ETH_P_8021Q:
case ETH_P_8021AD:
return parse_vlan(pkt, data, len);
2023-12-15 18:57:13 +08:00
case ETH_P_IP:
return parse_ipv4(pkt, data, len);
2023-12-15 18:57:13 +08:00
case ETH_P_IPV6:
return parse_ipv6(pkt, data, len);
2023-12-15 18:57:13 +08:00
case ETH_P_PPP_SES:
return parse_pppoe_ses(pkt, data, len);
2023-12-15 18:57:13 +08:00
case ETH_P_MPLS_UC:
return parse_mpls(pkt, data, len);
2024-06-05 16:44:32 +08:00
case 0x880b:
return parse_ppp(pkt, data, len);
2023-12-15 18:57:13 +08:00
default:
PACKET_LOG_UNSUPPORT_ETHPROTO(pkt, next_proto);
2023-12-15 18:57:13 +08:00
return data;
}
}
static inline const char *parse_l4(struct packet *pkt, uint8_t next_proto, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
switch (next_proto)
{
case IPPROTO_AH:
return parse_auth(pkt, data, len);
2023-12-15 18:57:13 +08:00
case IPPROTO_TCP:
return parse_tcp(pkt, data, len);
2023-12-15 18:57:13 +08:00
case IPPROTO_UDP:
return parse_udp(pkt, data, len);
2023-12-15 18:57:13 +08:00
case IPPROTO_IPIP:
return parse_ipv4(pkt, data, len);
2023-12-15 18:57:13 +08:00
case IPPROTO_IPV6:
return parse_ipv6(pkt, data, len);
2023-12-15 18:57:13 +08:00
case IPPROTO_GRE:
return parse_gre(pkt, data, len);
case IPPROTO_ICMP:
return parse_icmp(pkt, data, len);
case IPPROTO_ICMPV6:
return parse_icmp6(pkt, data, len);
2024-05-24 16:14:20 +08:00
case 115:
// L2TP
return parse_l2tpv3_over_ip(pkt, data, len);
2023-12-15 18:57:13 +08:00
default:
PACKET_LOG_UNSUPPORT_IPPROTO(pkt, next_proto);
2023-12-15 18:57:13 +08:00
return data;
}
}
/******************************************************************************
* Public API
******************************************************************************/
// return innermost payload
const char *packet_parse(struct packet *pkt, const char *data, uint16_t len)
2023-12-15 18:57:13 +08:00
{
pkt->frag_layer = NULL;
pkt->layers_used = 0;
pkt->layers_size = PACKET_MAX_LAYERS;
pkt->data_ptr = data;
pkt->data_len = len;
pkt->trim_len = 0;
2023-12-15 18:57:13 +08:00
return parse_ether(pkt, data, len);
2023-12-15 18:57:13 +08:00
}
void packet_print_str(const struct packet *pkt)
2023-12-15 18:57:13 +08:00
{
if (pkt == NULL)
2023-12-15 18:57:13 +08:00
{
return;
}
2024-05-29 17:55:44 +08:00
char buffer[2048] = {0};
printf("packet: %p, data_ptr: %p, data_len: %u, trim_len: %u, layers_used: %u, layers_size: %u\n",
pkt, pkt->data_ptr, pkt->data_len, pkt->trim_len,
pkt->layers_used, pkt->layers_size);
for (uint8_t i = 0; i < pkt->layers_used; i++)
2023-12-15 18:57:13 +08:00
{
2024-05-29 17:55:44 +08:00
int used = 0;
const struct raw_layer *layer = &pkt->layers[i];
2023-12-15 18:57:13 +08:00
printf(" layer[%u]: %p, type: %s, hdr_offset: %u, hdr_ptr: %p, hdr_len: %u, pld_ptr: %p, pld_len: %u\n",
2024-06-12 18:21:45 +08:00
i, layer, layer_proto_to_str(layer->type), layer->hdr_offset,
2023-12-15 18:57:13 +08:00
layer->hdr_ptr, layer->hdr_len, layer->pld_ptr, layer->pld_len);
2024-05-29 17:55:44 +08:00
switch (layer->type)
{
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_ETHER:
used = eth_hdr_to_str((const struct ethhdr *)layer->hdr_ptr, buffer, sizeof(buffer));
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_PWETH:
2024-05-29 17:55:44 +08:00
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_PPP:
2024-05-29 17:55:44 +08:00
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_L2TP:
2024-06-07 14:47:38 +08:00
used = l2tp_hdr_to_str((const struct l2tp_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
2024-05-29 17:55:44 +08:00
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_VLAN:
2024-06-05 11:41:46 +08:00
used = vlan_hdr_to_str((const struct vlan_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
2024-05-29 17:55:44 +08:00
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_PPPOE:
2024-05-29 17:55:44 +08:00
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_MPLS:
2024-06-05 10:39:57 +08:00
used = mpls_label_to_str((const struct mpls_label *)layer->hdr_ptr, buffer, sizeof(buffer));
break;
2024-05-29 17:55:44 +08:00
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_IPV4:
2024-05-29 17:55:44 +08:00
used = ipv4_hdr_to_str((const struct ip *)layer->hdr_ptr, buffer, sizeof(buffer));
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_IPV6:
2024-05-29 17:55:44 +08:00
used = ipv6_hdr_to_str((const struct ip6_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_IPAH:
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_GRE:
2024-06-05 16:44:32 +08:00
used = gre_hdr_to_str((const struct gre_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
2024-05-29 17:55:44 +08:00
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_UDP:
2024-05-29 17:55:44 +08:00
used = udp_hdr_to_str((const struct udphdr *)layer->hdr_ptr, buffer, sizeof(buffer));
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_TCP:
2024-05-29 17:55:44 +08:00
used = tcp_hdr_to_str((const struct tcphdr *)layer->hdr_ptr, buffer, sizeof(buffer));
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_ICMP:
2024-05-29 17:55:44 +08:00
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_ICMP6:
2024-05-29 17:55:44 +08:00
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_VXLAN:
2024-06-05 14:36:04 +08:00
used = vxlan_hdr_to_str((const struct vxlan_hdr *)layer->hdr_ptr, buffer, sizeof(buffer));
2024-05-29 17:55:44 +08:00
break;
2024-06-12 18:21:45 +08:00
case LAYER_PROTO_GTPV1_U:
2024-05-29 17:55:44 +08:00
break;
default:
break;
}
if (used)
{
printf(" %s\n", buffer);
}
2023-12-15 18:57:13 +08:00
}
}
2023-12-15 18:57:13 +08:00
// return 0 : found
// return -1 : not found
int packet_get_innermost_tuple2(const struct packet *pkt, struct tuple2 *tuple)
2023-12-15 18:57:13 +08:00
{
2024-03-11 15:04:18 +08:00
memset(tuple, 0, sizeof(struct tuple2));
const struct raw_layer *layer = NULL;
2023-12-15 18:57:13 +08:00
for (int8_t i = pkt->layers_used - 1; i >= 0; i--)
2023-12-15 18:57:13 +08:00
{
layer = &pkt->layers[i];
2023-12-15 18:57:13 +08:00
2024-06-12 18:21:45 +08:00
if (layer->type == LAYER_PROTO_IPV4 || layer->type == LAYER_PROTO_IPV6)
2023-12-15 18:57:13 +08:00
{
set_tuple2((const char *)pkt->data_ptr + layer->hdr_offset, layer->type, tuple);
2023-12-15 18:57:13 +08:00
return 0;
}
}
return -1;
}
// return 0 : found
// return -1 : not found
int packet_get_outermost_tuple2(const struct packet *pkt, struct tuple2 *tuple)
2023-12-15 18:57:13 +08:00
{
2024-03-11 15:04:18 +08:00
memset(tuple, 0, sizeof(struct tuple2));
const struct raw_layer *layer = NULL;
2023-12-15 18:57:13 +08:00
for (int8_t i = 0; i < pkt->layers_used; i++)
2023-12-15 18:57:13 +08:00
{
layer = &pkt->layers[i];
2023-12-15 18:57:13 +08:00
2024-06-12 18:21:45 +08:00
if (layer->type == LAYER_PROTO_IPV4 || layer->type == LAYER_PROTO_IPV6)
2023-12-15 18:57:13 +08:00
{
set_tuple2((const char *)pkt->data_ptr + layer->hdr_offset, layer->type, tuple);
2023-12-15 18:57:13 +08:00
return 0;
}
}
return -1;
}
// return 0 : found
// return -1 : not found
int packet_get_innermost_tuple4(const struct packet *pkt, struct tuple4 *tuple)
2023-12-15 18:57:13 +08:00
{
2024-03-11 15:04:18 +08:00
memset(tuple, 0, sizeof(struct tuple4));
const struct raw_layer *layer_l3 = NULL;
const struct raw_layer *layer_l4 = NULL;
const struct raw_layer *layer = NULL;
2023-12-15 18:57:13 +08:00
for (int8_t i = pkt->layers_used - 1; i >= 0; i--)
2023-12-15 18:57:13 +08:00
{
layer = &pkt->layers[i];
2023-12-15 18:57:13 +08:00
// first get L4 layer
2024-06-12 18:21:45 +08:00
if (layer->type == LAYER_PROTO_UDP || layer->type == LAYER_PROTO_TCP)
2023-12-15 18:57:13 +08:00
{
layer_l4 = layer;
continue;
}
// second get L3 layer
2024-06-12 18:21:45 +08:00
if (layer->type == LAYER_PROTO_IPV4 || layer->type == LAYER_PROTO_IPV6)
2023-12-15 18:57:13 +08:00
{
layer_l3 = layer;
break;
}
}
if (layer_l3 && layer_l4)
{
set_tuple4((const char *)pkt->data_ptr + layer_l3->hdr_offset, layer_l3->type, tuple);
set_tuple4((const char *)pkt->data_ptr + layer_l4->hdr_offset, layer_l4->type, tuple);
2023-12-15 18:57:13 +08:00
return 0;
}
else
{
return -1;
}
}
// return 0 : found
// return -1 : not found
int packet_get_outermost_tuple4(const struct packet *pkt, struct tuple4 *tuple)
2023-12-15 18:57:13 +08:00
{
2024-03-11 15:04:18 +08:00
memset(tuple, 0, sizeof(struct tuple4));
const struct raw_layer *layer_l3 = NULL;
const struct raw_layer *layer_l4 = NULL;
const struct raw_layer *layer = NULL;
2023-12-15 18:57:13 +08:00
for (int8_t i = 0; i < pkt->layers_used; i++)
2023-12-15 18:57:13 +08:00
{
layer = &pkt->layers[i];
2023-12-15 18:57:13 +08:00
// first get L3 layer
2024-06-12 18:21:45 +08:00
if (layer->type == LAYER_PROTO_IPV4 || layer->type == LAYER_PROTO_IPV6)
2023-12-15 18:57:13 +08:00
{
layer_l3 = layer;
continue;
}
// second get L4 layer
2024-06-12 18:21:45 +08:00
if (layer->type == LAYER_PROTO_UDP || layer->type == LAYER_PROTO_TCP)
2023-12-15 18:57:13 +08:00
{
layer_l4 = layer;
break;
}
}
if (layer_l3 && layer_l4)
{
set_tuple4((const char *)pkt->data_ptr + layer_l3->hdr_offset, layer_l3->type, tuple);
set_tuple4((const char *)pkt->data_ptr + layer_l4->hdr_offset, layer_l4->type, tuple);
2023-12-15 18:57:13 +08:00
return 0;
}
else
{
return -1;
}
}
// return 0 : found
// return -1 : not found
int packet_get_innermost_tuple6(const struct packet *pkt, struct tuple6 *tuple)
2023-12-15 18:57:13 +08:00
{
2024-03-11 15:04:18 +08:00
memset(tuple, 0, sizeof(struct tuple6));
const struct raw_layer *layer_l3 = NULL;
const struct raw_layer *layer_l4 = NULL;
const struct raw_layer *layer = NULL;
2024-04-11 19:44:02 +08:00
uint64_t domain = packet_get_domain(pkt);
2023-12-15 18:57:13 +08:00
for (int8_t i = pkt->layers_used - 1; i >= 0; i--)
2023-12-15 18:57:13 +08:00
{
layer = &pkt->layers[i];
2023-12-15 18:57:13 +08:00
// first get L4 layer
2024-06-12 18:21:45 +08:00
if (layer->type == LAYER_PROTO_UDP || layer->type == LAYER_PROTO_TCP)
2023-12-15 18:57:13 +08:00
{
layer_l4 = layer;
continue;
}
// second get L3 layer
2024-06-12 18:21:45 +08:00
if (layer->type == LAYER_PROTO_IPV4 || layer->type == LAYER_PROTO_IPV6)
2023-12-15 18:57:13 +08:00
{
layer_l3 = layer;
break;
}
}
2024-04-11 19:44:02 +08:00
if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1)
2023-12-15 18:57:13 +08:00
{
2024-04-11 19:44:02 +08:00
set_tuple6((const char *)pkt->data_ptr + layer_l3->hdr_offset, layer_l3->type, tuple, domain);
set_tuple6((const char *)pkt->data_ptr + layer_l4->hdr_offset, layer_l4->type, tuple, domain);
2023-12-15 18:57:13 +08:00
return 0;
}
else
{
return -1;
}
}
// return 0 : found
// return -1 : not found
int packet_get_outermost_tuple6(const struct packet *pkt, struct tuple6 *tuple)
2023-12-15 18:57:13 +08:00
{
2024-03-11 15:04:18 +08:00
memset(tuple, 0, sizeof(struct tuple6));
const struct raw_layer *layer_l3 = NULL;
const struct raw_layer *layer_l4 = NULL;
const struct raw_layer *layer = NULL;
2024-04-11 19:44:02 +08:00
uint64_t domain = packet_get_domain(pkt);
2023-12-15 18:57:13 +08:00
for (int8_t i = 0; i < pkt->layers_used; i++)
2023-12-15 18:57:13 +08:00
{
layer = &pkt->layers[i];
2023-12-15 18:57:13 +08:00
// first get L3 layer
2024-06-12 18:21:45 +08:00
if (layer->type == LAYER_PROTO_IPV4 || layer->type == LAYER_PROTO_IPV6)
2023-12-15 18:57:13 +08:00
{
layer_l3 = layer;
continue;
}
// second get L4 layer
2024-06-12 18:21:45 +08:00
if (layer->type == LAYER_PROTO_UDP || layer->type == LAYER_PROTO_TCP)
2023-12-15 18:57:13 +08:00
{
layer_l4 = layer;
break;
}
}
2024-04-11 19:44:02 +08:00
if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1)
2023-12-15 18:57:13 +08:00
{
2024-04-11 19:44:02 +08:00
set_tuple6((const char *)pkt->data_ptr + layer_l3->hdr_offset, layer_l3->type, tuple, domain);
set_tuple6((const char *)pkt->data_ptr + layer_l4->hdr_offset, layer_l4->type, tuple, domain);
2023-12-15 18:57:13 +08:00
return 0;
}
else
{
return -1;
}
}
const struct raw_layer *packet_get_innermost_raw_layer(const struct packet *pkt, enum layer_proto type)
2023-12-15 18:57:13 +08:00
{
const struct raw_layer *layer = NULL;
2023-12-15 18:57:13 +08:00
for (int8_t i = pkt->layers_used - 1; i >= 0; i--)
2023-12-15 18:57:13 +08:00
{
layer = &pkt->layers[i];
2024-06-12 18:21:45 +08:00
if (layer->type == type)
2023-12-15 18:57:13 +08:00
{
return layer;
}
}
return NULL;
}
const struct raw_layer *packet_get_outermost_raw_layer(const struct packet *pkt, enum layer_proto type)
2023-12-15 18:57:13 +08:00
{
const struct raw_layer *layer = NULL;
2023-12-15 18:57:13 +08:00
for (int8_t i = 0; i < pkt->layers_used; i++)
2023-12-15 18:57:13 +08:00
{
layer = &pkt->layers[i];
2024-06-12 18:21:45 +08:00
if (layer->type == type)
2023-12-15 18:57:13 +08:00
{
return layer;
}
}
return NULL;
}
// direction 1: E2I
// direction 0: I2E
uint64_t packet_get_hash(const struct packet *pkt, enum ldbc_method method, int direction)
2023-12-15 18:57:13 +08:00
{
uint64_t temp = 0;
uint64_t hash_value = 1;
int inner_addr_len = 0;
int outer_addr_len = 0;
const char *inner_src_addr = NULL;
const char *inner_dst_addr = NULL;
const char *outer_src_addr = NULL;
const char *outer_dst_addr = NULL;
struct tuple2 inner_addr;
struct tuple2 outer_addr;
if (pkt == NULL)
2023-12-15 18:57:13 +08:00
{
return hash_value;
}
if (packet_get_innermost_tuple2(pkt, &inner_addr) == -1)
2023-12-15 18:57:13 +08:00
{
return hash_value;
}
if (packet_get_outermost_tuple2(pkt, &outer_addr) == -1)
2023-12-15 18:57:13 +08:00
{
return hash_value;
}
if (inner_addr.ip_type == IP_TYPE_V4)
{
inner_src_addr = (const char *)&inner_addr.src_addr.v4;
inner_dst_addr = (const char *)&inner_addr.dst_addr.v4;
inner_addr_len = sizeof(struct in_addr);
}
else
{
inner_src_addr = (const char *)&inner_addr.src_addr.v6;
inner_dst_addr = (const char *)&inner_addr.dst_addr.v6;
inner_addr_len = sizeof(struct in6_addr);
}
if (outer_addr.ip_type == IP_TYPE_V4)
{
outer_src_addr = (const char *)&outer_addr.src_addr.v4;
outer_dst_addr = (const char *)&outer_addr.dst_addr.v4;
outer_addr_len = sizeof(struct in_addr);
}
else
{
outer_src_addr = (const char *)&outer_addr.src_addr.v6;
outer_dst_addr = (const char *)&outer_addr.dst_addr.v6;
outer_addr_len = sizeof(struct in6_addr);
}
switch (method)
{
case LDBC_METHOD_HASH_INT_IP:
if (direction)
{
// direction 1: E2I
HASH_VALUE(outer_dst_addr, outer_addr_len, hash_value);
}
else
{
// direction 0: I2E
HASH_VALUE(outer_src_addr, outer_addr_len, hash_value);
}
break;
case LDBC_METHOD_HASH_EXT_IP:
if (direction)
{
// direction 1: E2I
HASH_VALUE(outer_src_addr, outer_addr_len, hash_value);
}
else
{
// direction 0: I2E
HASH_VALUE(outer_dst_addr, outer_addr_len, hash_value);
}
break;
case LDBC_METHOD_HASH_INT_IP_AND_EXT_IP:
HASH_VALUE(outer_src_addr, outer_addr_len, hash_value);
HASH_VALUE(outer_dst_addr, outer_addr_len, temp);
hash_value = hash_value ^ temp;
break;
case LDBC_METHOD_HASH_INNERMOST_INT_IP:
if (direction)
{
// direction 1: E2I
HASH_VALUE(inner_dst_addr, inner_addr_len, hash_value);
}
else
{
// direction 0: I2E
HASH_VALUE(inner_src_addr, inner_addr_len, hash_value);
}
break;
case LDBC_METHOD_HASH_INNERMOST_EXT_IP:
if (direction)
{
// direction 1: E2I
HASH_VALUE(inner_src_addr, inner_addr_len, hash_value);
}
else
{
// direction 0: I2E
HASH_VALUE(inner_dst_addr, inner_addr_len, hash_value);
}
break;
default:
return hash_value;
}
return hash_value;
2024-04-11 19:44:02 +08:00
}