packet parser support L2TPv2

This commit is contained in:
luwenpeng
2024-05-24 16:14:20 +08:00
parent 570c93e616
commit 6c1f9d390c
5 changed files with 468 additions and 45 deletions

View File

@@ -14,33 +14,34 @@ enum layer_type
LAYER_TYPE_ETHER = 1 << 0, LAYER_TYPE_ETHER = 1 << 0,
LAYER_TYPE_PPP = 1 << 1, LAYER_TYPE_PPP = 1 << 1,
LAYER_TYPE_HDLC = 1 << 2, LAYER_TYPE_HDLC = 1 << 2,
LAYER_TYPE_L2 = (LAYER_TYPE_ETHER | LAYER_TYPE_PPP | LAYER_TYPE_HDLC), LAYER_TYPE_L2TP = 1 << 3,
LAYER_TYPE_L2 = (LAYER_TYPE_ETHER | LAYER_TYPE_PPP | LAYER_TYPE_HDLC | LAYER_TYPE_L2TP),
// L2 -- tunnel // L2 -- tunnel
LAYER_TYPE_VLAN = 1 << 3, LAYER_TYPE_VLAN = 1 << 4,
LAYER_TYPE_PPPOE = 1 << 4, LAYER_TYPE_PPPOE = 1 << 5,
LAYER_TYPE_MPLS = 1 << 5, LAYER_TYPE_MPLS = 1 << 6,
LAYER_TYPE_L2_TUN = (LAYER_TYPE_VLAN | LAYER_TYPE_PPPOE | LAYER_TYPE_MPLS), LAYER_TYPE_L2_TUN = (LAYER_TYPE_VLAN | LAYER_TYPE_PPPOE | LAYER_TYPE_MPLS),
// L3 -- network layer // L3 -- network layer
LAYER_TYPE_IPV4 = 1 << 6, LAYER_TYPE_IPV4 = 1 << 7,
LAYER_TYPE_IPV6 = 1 << 7, LAYER_TYPE_IPV6 = 1 << 8,
LAYER_TYPE_L3 = (LAYER_TYPE_IPV4 | LAYER_TYPE_IPV6), LAYER_TYPE_L3 = (LAYER_TYPE_IPV4 | LAYER_TYPE_IPV6),
// L3 -- tunnel // L3 -- tunnel
LAYER_TYPE_GRE = 1 << 8, LAYER_TYPE_GRE = 1 << 9,
LAYER_TYPE_L3_TUN = (LAYER_TYPE_GRE), LAYER_TYPE_L3_TUN = (LAYER_TYPE_GRE),
// L4 -- transport layer // L4 -- transport layer
LAYER_TYPE_UDP = 1 << 9, LAYER_TYPE_UDP = 1 << 10,
LAYER_TYPE_TCP = 1 << 10, LAYER_TYPE_TCP = 1 << 11,
LAYER_TYPE_ICMP = 1 << 11, LAYER_TYPE_ICMP = 1 << 12,
LAYER_TYPE_ICMP6 = 1 << 12, LAYER_TYPE_ICMP6 = 1 << 13,
LAYER_TYPE_L4 = (LAYER_TYPE_UDP | LAYER_TYPE_TCP | LAYER_TYPE_ICMP | LAYER_TYPE_ICMP6), LAYER_TYPE_L4 = (LAYER_TYPE_UDP | LAYER_TYPE_TCP | LAYER_TYPE_ICMP | LAYER_TYPE_ICMP6),
// L4 -- tunnel // L4 -- tunnel
LAYER_TYPE_VXLAN = 1 << 13, LAYER_TYPE_VXLAN = 1 << 14,
LAYER_TYPE_GTPV1_U = 1 << 14, LAYER_TYPE_GTPV1_U = 1 << 15,
// ALL // ALL
LAYER_TYPE_ALL = (LAYER_TYPE_L2 | LAYER_TYPE_L2_TUN | LAYER_TYPE_L3 | LAYER_TYPE_L3_TUN | LAYER_TYPE_L4 | LAYER_TYPE_VXLAN | LAYER_TYPE_GTPV1_U), LAYER_TYPE_ALL = (LAYER_TYPE_L2 | LAYER_TYPE_L2_TUN | LAYER_TYPE_L3 | LAYER_TYPE_L3_TUN | LAYER_TYPE_L4 | LAYER_TYPE_VXLAN | LAYER_TYPE_GTPV1_U),

View File

@@ -20,28 +20,28 @@
#define likely(expr) __builtin_expect((expr), 1) #define likely(expr) __builtin_expect((expr), 1)
#define unlikely(expr) __builtin_expect((expr), 0) #define unlikely(expr) __builtin_expect((expr), 0)
#define PACKET_LOG_DATA_INSUFFICIENCY(type) \ #define PACKET_LOG_DATA_INSUFFICIENCY(type) \
{ \ { \
PACKET_LOG_ERROR("layer: %s, data insufficiency", \ PACKET_LOG_WARN("layer: %s, data insufficiency", \
layer_type_to_str((type))); \ layer_type_to_str((type))); \
} }
#define PACKET_LOG_UNSUPPORT_PROTO(tag, next_proto) \ #define PACKET_LOG_UNSUPPORT_PROTO(tag, next_proto) \
{ \ { \
PACKET_LOG_ERROR("%s: unsupport next proto %d", \ PACKET_LOG_WARN("%s: unsupport next proto %d", \
(tag), (next_proto)); \ (tag), (next_proto)); \
} }
#define PACKET_LOG_UNSUPPORT_ETHPROTO(tag, next_proto) \ #define PACKET_LOG_UNSUPPORT_ETHPROTO(tag, next_proto) \
{ \
PACKET_LOG_ERROR("%s: unsupport next proto %d: %s", \
(tag), (next_proto), ethproto_to_str(next_proto)); \
}
#define PACKET_LOG_UNSUPPORT_IPPROTO(tag, next_proto) \
{ \ { \
PACKET_LOG_ERROR("%s: unsupport next proto %d: %s", \ PACKET_LOG_WARN("%s: unsupport next eth proto %d: %s", \
(tag), (next_proto), ipproto_to_str(next_proto)); \ (tag), (next_proto), ethproto_to_str(next_proto)); \
}
#define PACKET_LOG_UNSUPPORT_IPPROTO(tag, next_proto) \
{ \
PACKET_LOG_WARN("%s: unsupport next ip proto %d: %s", \
(tag), (next_proto), ipproto_to_str(next_proto)); \
} }
/****************************************************************************** /******************************************************************************
@@ -61,10 +61,15 @@ 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_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_gre_hdr_len(const char *data, uint16_t len);
static inline uint16_t get_l2tpv2_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_ether(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_ppp(struct packet *pkt, const char *data, uint16_t len); static inline const char *parse_ppp(struct packet *pkt, const char *data, uint16_t len);
static inline const char *parse_l2tpv2(struct packet *pkt, const char *data, uint16_t len);
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);
// 数据链路层 -- 隧道 // 数据链路层 -- 隧道
static inline const char *parse_vlan(struct packet *pkt, const char *data, uint16_t len); 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_pppoe_ses(struct packet *pkt, const char *data, uint16_t len);
@@ -291,6 +296,8 @@ static inline const char *layer_type_to_str(enum layer_type type)
return "PPP"; return "PPP";
case LAYER_TYPE_HDLC: case LAYER_TYPE_HDLC:
return "HDLC"; return "HDLC";
case LAYER_TYPE_L2TP:
return "L2TP";
case LAYER_TYPE_VLAN: case LAYER_TYPE_VLAN:
return "VLAN"; return "VLAN";
case LAYER_TYPE_PPPOE: case LAYER_TYPE_PPPOE:
@@ -307,6 +314,10 @@ static inline const char *layer_type_to_str(enum layer_type type)
return "UDP"; return "UDP";
case LAYER_TYPE_TCP: case LAYER_TYPE_TCP:
return "TCP"; return "TCP";
case LAYER_TYPE_ICMP:
return "ICMP";
case LAYER_TYPE_ICMP6:
return "ICMP6";
case LAYER_TYPE_VXLAN: case LAYER_TYPE_VXLAN:
return "VXLAN"; return "VXLAN";
case LAYER_TYPE_GTPV1_U: case LAYER_TYPE_GTPV1_U:
@@ -646,6 +657,85 @@ static inline uint16_t get_gre_hdr_len(const char *data, uint16_t len)
return hdr_offset; return hdr_offset;
} }
static inline uint16_t get_l2tpv2_hdr_len(const char *data, uint16_t len)
{
/*
* Layer Two Tunneling Protocol "L2TP"
* https://datatracker.ietf.org/doc/html/rfc2661
*
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |T|L|x|x|S|x|O|P|x|x|x|x| Ver | Length (opt) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Tunnel ID | Session ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Ns (opt) | Nr (opt) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Offset Size (opt) | Offset pad... (opt)
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Figure 3.1 L2TP Message Header
*/
#define CONTROL_BIT(msg_info) (msg_info & 0x8000) // Type bit control = 1 data = 0
#define LENGTH_BIT(msg_info) (msg_info & 0x4000) // Length bit = 1
#define SEQUENCE_BIT(msg_info) (msg_info & 0x0800) // SEQUENCE bit = 1 Ns and Nr fields
#define OFFSET_BIT(msg_info) (msg_info & 0x0200) // Offset
#define PRIORITY_BIT(msg_info) (msg_info & 0x0100) // Priority
#define L2TP_VERSION(msg_info) (msg_info & 0x000f) // Version of l2tp
if (unlikely(len < 6))
{
return 0;
}
uint16_t control = ntohs(*((uint16_t *)data));
if (L2TP_VERSION(control) != 2)
{
return 0;
}
if (CONTROL_BIT(control))
{
if (LENGTH_BIT(control) != 1 || SEQUENCE_BIT(control) != 1 || OFFSET_BIT(control) != 0 || PRIORITY_BIT(control) != 0)
{
return 0;
}
else
{
return ntohs(*((uint16_t *)(data + 2)));
}
}
else
{
uint16_t skip_len = 2;
if (LENGTH_BIT(control))
{
skip_len += 2; // skip length field
}
skip_len += 2; // skip tunnel id field
skip_len += 2; // skip session id field
if (SEQUENCE_BIT(control))
{
skip_len += 2; // skip ns field
skip_len += 2; // skip nr field
}
if (OFFSET_BIT(control))
{
if (skip_len + 2 > len)
{
return 0;
}
return ntohs(*((uint16_t *)(data + skip_len)));
}
else
{
return skip_len;
}
}
}
static inline const char *parse_ether(struct packet *pkt, const char *data, uint16_t len) static inline const char *parse_ether(struct packet *pkt, const char *data, uint16_t len)
{ {
if (unlikely(len < sizeof(struct ethhdr))) if (unlikely(len < sizeof(struct ethhdr)))
@@ -695,6 +785,47 @@ static inline const char *parse_ppp(struct packet *pkt, const char *data, uint16
} }
} }
static inline const char *parse_l2tpv2(struct packet *pkt, const char *data, uint16_t len)
{
#define CONTROL_BIT(msg_info) (msg_info & 0x8000) // Type bit control = 1 data = 0
uint16_t hdr_len = get_l2tpv2_hdr_len(data, len);
if (unlikely(hdr_len == 0 || hdr_len > len))
{
PACKET_LOG_DATA_INSUFFICIENCY(LAYER_TYPE_L2TP);
return data;
}
struct packet_layer *layer = get_free_layer(pkt);
if (unlikely(layer == NULL))
{
return data;
}
SET_LAYER(pkt, layer, LAYER_TYPE_L2TP, hdr_len, data, len);
uint16_t control = ntohs(*((uint16_t *)data));
if (CONTROL_BIT(control))
{
return layer->pld_ptr;
}
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)
{
// TODO
return data;
}
static inline const char *parse_l2tpv3_over_ip(struct packet *pkt, const char *data, uint16_t len)
{
// TODO
return data;
}
static inline const char *parse_vlan(struct packet *pkt, const char *data, uint16_t len) static inline const char *parse_vlan(struct packet *pkt, const char *data, uint16_t len)
{ {
struct vlan_hdr struct vlan_hdr
@@ -742,7 +873,7 @@ static inline const char *parse_pppoe_ses(struct packet *pkt, const char *data,
switch (next_proto) switch (next_proto)
{ {
// TESTED // TESTED
case PPPOE_TYPE_IPV4: case PPPOE_TYPE_IPV4:
return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len); return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len);
case PPPOE_TYPE_IPV6: case PPPOE_TYPE_IPV6:
@@ -882,7 +1013,7 @@ static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint1
// ip fragmented // ip fragmented
if (ipv4_hdr_get_mf_flag(hdr) || ipv4_hdr_get_frag_offset(hdr)) if (ipv4_hdr_get_mf_flag(hdr) || ipv4_hdr_get_frag_offset(hdr))
{ {
PACKET_LOG_DEBUG("ip is fragmented"); PACKET_LOG_WARN("ip is fragmented");
pkt->frag_layer = layer; pkt->frag_layer = layer;
return layer->pld_ptr; return layer->pld_ptr;
} }
@@ -910,11 +1041,13 @@ static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint1
// ipv6 fragment // ipv6 fragment
if (next_proto == IPPROTO_FRAGMENT) if (next_proto == IPPROTO_FRAGMENT)
{ {
PACKET_LOG_DEBUG("ipv6 is fragmented"); PACKET_LOG_WARN("ipv6 is fragmented");
pkt->frag_layer = layer; pkt->frag_layer = layer;
return layer->pld_ptr; return layer->pld_ptr;
} }
// TODO parse ipv6 extension headers
// TESTED // TESTED
return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len); return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len);
} }
@@ -986,6 +1119,27 @@ static inline const char *parse_udp(struct packet *pkt, const char *data, uint16
return parse_gtpv1_u(pkt, layer->pld_ptr, layer->pld_len); return parse_gtpv1_u(pkt, layer->pld_ptr, layer->pld_len);
} }
if (udp_hdr_get_dst_port(hdr) == 1701)
{
// L2TP_DPORT 1701
if (unlikely(layer->pld_len < 8))
{
return layer->pld_ptr;
}
uint16_t control = ntohs(*((uint16_t *)layer->pld_ptr));
switch (L2TP_VERSION(control))
{
case 2:
// TESTED
return parse_l2tpv2(pkt, layer->pld_ptr, layer->pld_len);
case 3:
return parse_l2tpv3_over_udp(pkt, layer->pld_ptr, layer->pld_len);
default:
return layer->pld_ptr;
}
}
return layer->pld_ptr; return layer->pld_ptr;
} }
@@ -1159,6 +1313,9 @@ static inline const char *parse_l4(struct packet *pkt, uint8_t next_proto, const
// TESTED // TESTED
case IPPROTO_ICMPV6: case IPPROTO_ICMPV6:
return parse_icmp6(pkt, data, len); return parse_icmp6(pkt, data, len);
case 115:
// L2TP
return parse_l2tpv3_over_ip(pkt, data, len);
default: default:
PACKET_LOG_UNSUPPORT_IPPROTO("l4", next_proto); PACKET_LOG_UNSUPPORT_IPPROTO("l4", next_proto);
return data; return data;

View File

@@ -4,7 +4,6 @@
#include "packet_priv.h" #include "packet_priv.h"
/****************************************************************************** /******************************************************************************
* Pcap file: 1-ETH_VLAN_VLAN_IP4_IP4_UDP.pcap
* [Protocols in frame: eth:ethertype:vlan:ethertype:vlan:ethertype:ip:ip:udp:data] * [Protocols in frame: eth:ethertype:vlan:ethertype:vlan:ethertype:ip:ip:udp:data]
****************************************************************************** ******************************************************************************
* *
@@ -221,7 +220,6 @@ TEST(PACKET, ETH_VLAN_VLAN_IP4_IP4_UDP)
#endif #endif
/****************************************************************************** /******************************************************************************
* Pcap file: 2-ETH_IP6_IP4_TCP_SSH.pcap
* [Protocols in frame: eth:ethertype:ipv6:ip:tcp:ssh] * [Protocols in frame: eth:ethertype:ipv6:ip:tcp:ssh]
****************************************************************************** ******************************************************************************
* *
@@ -447,7 +445,6 @@ TEST(PACKET, ETH_IP6_IP4_TCP_SSH)
#endif #endif
/****************************************************************************** /******************************************************************************
* Pcap file: 3-ETH_VLAN_IP6_IP4_GRE_PPP_IP4_UDP_DNS.pcap
* [Protocols in frame: eth:ethertype:vlan:ethertype:ipv6:ip:gre:ppp:ip:udp:dns] * [Protocols in frame: eth:ethertype:vlan:ethertype:ipv6:ip:gre:ppp:ip:udp:dns]
****************************************************************************** ******************************************************************************
* *
@@ -730,7 +727,6 @@ TEST(PACKET, ETH_VLAN_IP6_IP4_GRE_PPP_IP4_UDP_DNS)
#endif #endif
/****************************************************************************** /******************************************************************************
* Pcap file: 4-ETH_IP4_IP6_TCP.pcap
* [Protocols in frame: eth:ethertype:ip:ipv6:tcp] * [Protocols in frame: eth:ethertype:ip:ipv6:tcp]
****************************************************************************** ******************************************************************************
* *
@@ -929,7 +925,6 @@ TEST(PACKET, ETH_IP4_IP6_TCP)
#endif #endif
/****************************************************************************** /******************************************************************************
* Pcap file: 5-ETH_IP6_IP6_UDP.pcap
* [Protocols in frame: eth:ethertype:ipv6:ipv6:udp:data] * [Protocols in frame: eth:ethertype:ipv6:ipv6:udp:data]
****************************************************************************** ******************************************************************************
* *
@@ -1108,7 +1103,6 @@ TEST(PACKET, ETH_IP6_IP6_UDP)
#endif #endif
/****************************************************************************** /******************************************************************************
* Pcap file: 6-ETH_MPLS_IP4_TCP.pcap
* [Protocols in frame: eth:ethertype:mpls:ip:tcp] * [Protocols in frame: eth:ethertype:mpls:ip:tcp]
****************************************************************************** ******************************************************************************
* *
@@ -1306,7 +1300,6 @@ TEST(PACKET, ETH_MPLS_IP4_TCP)
#endif #endif
/****************************************************************************** /******************************************************************************
* Pcap file: 7-ETH_MPLS_MPLS_IP4_TCP.pcap
* [Protocols in frame: eth:ethertype:mpls:ip:tcp] * [Protocols in frame: eth:ethertype:mpls:ip:tcp]
****************************************************************************** ******************************************************************************
* *
@@ -1517,7 +1510,6 @@ TEST(PACKET, ETH_MPLS_MPLS_IP4_TCP)
#endif #endif
/****************************************************************************** /******************************************************************************
* Pcap file: 8-ETH_VLAN_PPPOE_IP4_TCP.pcap
* [Protocols in frame: eth:ethertype:vlan:ethertype:pppoes:ppp:ip:tcp] * [Protocols in frame: eth:ethertype:vlan:ethertype:pppoes:ppp:ip:tcp]
****************************************************************************** ******************************************************************************
* *
@@ -1739,7 +1731,6 @@ TEST(PACKET, ETH_VLAN_PPPOE_IP4_TCP)
#endif #endif
/****************************************************************************** /******************************************************************************
* Pcap file: 9-ETH_IP6_UDP_GTP_IP6_TCP_TLS.pcap
* [Protocols in frame: eth:ethertype:ipv6:udp:gtp:ipv6:tcp:ja3:tls] * [Protocols in frame: eth:ethertype:ipv6:udp:gtp:ipv6:tcp:ja3:tls]
****************************************************************************** ******************************************************************************
* *
@@ -2019,7 +2010,6 @@ TEST(PACKET, ETH_IP6_UDP_GTP_IP6_TCP_TLS)
#endif #endif
/****************************************************************************** /******************************************************************************
* Pcap file: 10-ETH_IP6_UDP_GTP_IP4_TCP_TLS.pcap
* [Protocols in frame: eth:ethertype:ipv6:udp:gtp:ip:tcp:ja3:tls] * [Protocols in frame: eth:ethertype:ipv6:udp:gtp:ip:tcp:ja3:tls]
****************************************************************************** ******************************************************************************
* *
@@ -2312,7 +2302,6 @@ TEST(PACKET, ETH_IP6_UDP_GTP_IP4_TCP_TLS)
#endif #endif
/****************************************************************************** /******************************************************************************
* Pcap file: 11-ETH_IP4_UDP_VXLAN_ETH_IP4_UDP_DNS.pcap
* [Protocols in frame: eth:ethertype:ip:udp:vxlan:eth:ethertype:ip:udp:dns] * [Protocols in frame: eth:ethertype:ip:udp:vxlan:eth:ethertype:ip:udp:dns]
****************************************************************************** ******************************************************************************
* *
@@ -2544,7 +2533,6 @@ TEST(PACKET, ETH_IP4_UDP_VXLAN_ETH_IP4_UDP_DNS)
#endif #endif
/****************************************************************************** /******************************************************************************
* Pcap file: 12-ETH_MPLS_MPLS_PWETHCW_ETH_ARP.pcap
* [Protocols in frame: eth:ethertype:mpls:pwethheuristic:pwethcw:eth:ethertype:arp] * [Protocols in frame: eth:ethertype:mpls:pwethheuristic:pwethcw:eth:ethertype:arp]
****************************************************************************** ******************************************************************************
* *
@@ -2954,6 +2942,223 @@ TEST(PACKET, ETH_IP6_ICMP6)
} }
#endif #endif
/******************************************************************************
* [Protocols in frame: eth:ethertype:ip:udp:l2tp:ppp:ip:udp:nbns]
******************************************************************************
*
* Frame 1: 150 bytes on wire (1200 bits), 150 bytes captured (1200 bits)
* Ethernet II, Src: LCFCElectron_43:38:37 (28:d2:44:43:38:37), Dst: c0:00:14:8c:00:00 (c0:00:14:8c:00:00)
* Destination: c0:00:14:8c:00:00 (c0:00:14:8c:00:00)
* Source: LCFCElectron_43:38:37 (28:d2:44:43:38:37)
* Type: IPv4 (0x0800)
* Internet Protocol Version 4, Src: 172.16.0.100, Dst: 172.16.0.254
* 0100 .... = Version: 4
* .... 0101 = Header Length: 20 bytes (5)
* Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
* 0000 00.. = Differentiated Services Codepoint: Default (0)
* .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0)
* Total Length: 136
* Identification: 0x06ca (1738)
* 000. .... = Flags: 0x0
* 0... .... = Reserved bit: Not set
* .0.. .... = Don't fragment: Not set
* ..0. .... = More fragments: Not set
* ...0 0000 0000 0000 = Fragment Offset: 0
* Time to Live: 128
* Protocol: UDP (17)
* Header Checksum: 0xda18 [correct]
* [Header checksum status: Good]
* [Calculated Checksum: 0xda18]
* Source Address: 172.16.0.100
* Destination Address: 172.16.0.254
* User Datagram Protocol, Src Port: 1701, Dst Port: 1701
* Source Port: 1701
* Destination Port: 1701
* Length: 116
* Checksum: 0x962f [correct]
* [Calculated Checksum: 0x962f]
* [Checksum Status: Good]
* [Stream index: 0]
* [Timestamps]
* [Time since first frame: 0.000000000 seconds]
* [Time since previous frame: 0.000000000 seconds]
* UDP payload (108 bytes)
* Layer 2 Tunneling Protocol
* Flags: 0x4002, Type: Data Message, Length Bit
* 0... .... .... .... = Type: Data Message (0)
* .1.. .... .... .... = Length Bit: Length field is present
* .... 0... .... .... = Sequence Bit: Ns and Nr fields are not present
* .... ..0. .... .... = Offset bit: Offset size field is not present
* .... ...0 .... .... = Priority: No priority
* .... .... .... 0010 = Version: 2
* Length: 108
* Tunnel ID: 28998
* Session ID: 2
* Point-to-Point Protocol
* Address: 0xff
* Control: 0x03
* Protocol: Internet Protocol version 4 (0x0021)
* Internet Protocol Version 4, Src: 172.16.2.100, Dst: 255.255.255.255
* 0100 .... = Version: 4
* .... 0101 = Header Length: 20 bytes (5)
* Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
* 0000 00.. = Differentiated Services Codepoint: Default (0)
* .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0)
* Total Length: 96
* Identification: 0x0004 (4)
* 000. .... = Flags: 0x0
* 0... .... = Reserved bit: Not set
* .0.. .... = Don't fragment: Not set
* ..0. .... = More fragments: Not set
* ...0 0000 0000 0000 = Fragment Offset: 0
* Time to Live: 128
* Protocol: UDP (17)
* Header Checksum: 0x8c15 [correct]
* [Header checksum status: Good]
* [Calculated Checksum: 0x8c15]
* Source Address: 172.16.2.100
* Destination Address: 255.255.255.255
* User Datagram Protocol, Src Port: 137, Dst Port: 137
* Source Port: 137
* Destination Port: 137
* Length: 76
* Checksum: 0xba80 [correct]
* [Calculated Checksum: 0xba80]
* [Checksum Status: Good]
* [Stream index: 1]
* [Timestamps]
* [Time since first frame: 0.000000000 seconds]
* [Time since previous frame: 0.000000000 seconds]
* UDP payload (68 bytes)
* NetBIOS Name Service
*/
unsigned char data15[] = {
0xc0, 0x00, 0x14, 0x8c, 0x00, 0x00, 0x28, 0xd2, 0x44, 0x43, 0x38, 0x37, 0x08, 0x00, 0x45, 0x00, 0x00, 0x88, 0x06, 0xca, 0x00, 0x00, 0x80, 0x11, 0xda, 0x18,
0xac, 0x10, 0x00, 0x64, 0xac, 0x10, 0x00, 0xfe, 0x06, 0xa5, 0x06, 0xa5, 0x00, 0x74, 0x96, 0x2f, 0x40, 0x02, 0x00, 0x6c, 0x71, 0x46, 0x00, 0x02, 0xff, 0x03,
0x00, 0x21, 0x45, 0x00, 0x00, 0x60, 0x00, 0x04, 0x00, 0x00, 0x80, 0x11, 0x8c, 0x15, 0xac, 0x10, 0x02, 0x64, 0xff, 0xff, 0xff, 0xff, 0x00, 0x89, 0x00, 0x89,
0x00, 0x4c, 0xba, 0x80, 0xc6, 0x46, 0x29, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x45, 0x4a, 0x45, 0x4a, 0x45, 0x46, 0x43, 0x4e, 0x46,
0x44, 0x45, 0x4e, 0x43, 0x4e, 0x46, 0x45, 0x45, 0x49, 0x45, 0x4a, 0x45, 0x4f, 0x45, 0x4c, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x41, 0x41, 0x00, 0x00, 0x20,
0x00, 0x01, 0xc0, 0x0c, 0x00, 0x20, 0x00, 0x01, 0x00, 0x04, 0x93, 0xe0, 0x00, 0x06, 0x00, 0x00, 0xac, 0x10, 0x02, 0x64};
#if 1
TEST(PACKET, ETH_IP4_UDP_L2TPV2_PPP_IP4_UDP)
{
char buffer[256];
struct packet handler;
const char *payload = packet_parse(&handler, (const char *)data15, sizeof(data15));
EXPECT_TRUE(payload != nullptr);
EXPECT_TRUE((char *)payload - (char *)&data15 == 14 + 20 + 8 + 8 + 4 + 20 + 8);
packet_print(&handler);
/******************************************************
* packet_get_outermost/innermost_layer
******************************************************/
// LAYER_TYPE_ETHER
const struct packet_layer *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_TYPE_ETHER);
EXPECT_TRUE(outer_eth_record != nullptr);
EXPECT_TRUE(outer_eth_record->hdr_offset == 0);
EXPECT_TRUE(outer_eth_record->hdr_len == 14);
EXPECT_TRUE(outer_eth_record->pld_len == 136);
// LAYER_TYPE_L2
const struct packet_layer *outer_l2_record = packet_get_outermost_layer(&handler, LAYER_TYPE_L2);
EXPECT_TRUE(outer_l2_record != nullptr);
EXPECT_TRUE(outer_l2_record == outer_eth_record);
// LAYER_TYPE_IPV4
const struct packet_layer *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_TYPE_IPV4);
EXPECT_TRUE(outer_ipv4_record != nullptr);
EXPECT_TRUE(outer_ipv4_record->hdr_offset == 14);
EXPECT_TRUE(outer_ipv4_record->hdr_len == 20);
EXPECT_TRUE(outer_ipv4_record->pld_len == 116);
// LAYER_TYPE_L3
const struct packet_layer *outer_l3_record = packet_get_outermost_layer(&handler, LAYER_TYPE_L3);
EXPECT_TRUE(outer_l3_record != nullptr);
EXPECT_TRUE(outer_l3_record == outer_ipv4_record);
// LAYER_TYPE_UDP
const struct packet_layer *outer_udp_record = packet_get_outermost_layer(&handler, LAYER_TYPE_UDP);
EXPECT_TRUE(outer_udp_record != nullptr);
EXPECT_TRUE(outer_udp_record->hdr_offset == 34);
EXPECT_TRUE(outer_udp_record->hdr_len == 8);
EXPECT_TRUE(outer_udp_record->pld_len == 108);
// LAYER_TYPE_L4
const struct packet_layer *outer_l4_record = packet_get_outermost_layer(&handler, LAYER_TYPE_L4);
EXPECT_TRUE(outer_l4_record != nullptr);
EXPECT_TRUE(outer_l4_record == outer_udp_record);
// LAYER_TYPE_L2TP
const struct packet_layer *outer_l2tpv2_record = packet_get_outermost_layer(&handler, LAYER_TYPE_L2TP);
EXPECT_TRUE(outer_l2tpv2_record != nullptr);
EXPECT_TRUE(outer_l2tpv2_record->hdr_offset == 42);
EXPECT_TRUE(outer_l2tpv2_record->hdr_len == 8);
EXPECT_TRUE(outer_l2tpv2_record->pld_len == 100);
// LAYER_TYPE_PPP
const struct packet_layer *outer_ppp_record = packet_get_outermost_layer(&handler, LAYER_TYPE_PPP);
EXPECT_TRUE(outer_ppp_record != nullptr);
EXPECT_TRUE(outer_ppp_record->hdr_offset == 50);
EXPECT_TRUE(outer_ppp_record->hdr_len == 4);
EXPECT_TRUE(outer_ppp_record->pld_len == 96);
// LAYER_TYPE_IPV4
const struct packet_layer *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_TYPE_IPV4);
EXPECT_TRUE(inner_ipv4_record != nullptr);
EXPECT_TRUE(inner_ipv4_record->hdr_offset == 54);
EXPECT_TRUE(inner_ipv4_record->hdr_len == 20);
EXPECT_TRUE(inner_ipv4_record->pld_len == 76);
// LAYER_TYPE_L3
const struct packet_layer *inner_l3_record = packet_get_innermost_layer(&handler, LAYER_TYPE_L3);
EXPECT_TRUE(inner_l3_record != nullptr);
EXPECT_TRUE(inner_l3_record == inner_ipv4_record);
// LAYER_TYPE_UDP
const struct packet_layer *inner_udp_record = packet_get_innermost_layer(&handler, LAYER_TYPE_UDP);
EXPECT_TRUE(inner_udp_record != nullptr);
EXPECT_TRUE(inner_udp_record->hdr_offset == 74);
EXPECT_TRUE(inner_udp_record->hdr_len == 8);
EXPECT_TRUE(inner_udp_record->pld_len == 68);
// LAYER_TYPE_L4
const struct packet_layer *inner_l4_record = packet_get_innermost_layer(&handler, LAYER_TYPE_L4);
EXPECT_TRUE(inner_l4_record != nullptr);
EXPECT_TRUE(inner_l4_record == inner_udp_record);
/******************************************************
* packet_get_outermost/innermost_tuple4
******************************************************/
struct tuple4 outer_tuple4;
struct tuple4 inner_tuple4;
EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0);
EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0);
memset(buffer, 0, sizeof(buffer));
tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer));
EXPECT_STREQ(buffer, "172.16.0.100:1701-172.16.0.254:1701");
memset(buffer, 0, sizeof(buffer));
tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer));
EXPECT_STREQ(buffer, "172.16.2.100:137-255.255.255.255:137");
}
#endif
#if 1 #if 1
TEST(PACKET, HASH_VALUE) TEST(PACKET, HASH_VALUE)
{ {

View File

@@ -35,5 +35,8 @@ gtest_discover_tests(gtest_inject_tcp_payload_fin_rst_after_recv_c2s_first_paylo
add_executable(packet_injector packet_injector.cpp) add_executable(packet_injector packet_injector.cpp)
target_link_libraries(packet_injector core gtest) target_link_libraries(packet_injector core gtest)
add_executable(packet_parser packet_parser.cpp)
target_link_libraries(packet_parser packet pcap)
file(COPY ./conf/ DESTINATION ./conf/) file(COPY ./conf/ DESTINATION ./conf/)
file(COPY ./pcap/ DESTINATION ./pcap/) file(COPY ./pcap/ DESTINATION ./pcap/)

57
test/packet_parser.cpp Normal file
View File

@@ -0,0 +1,57 @@
#include <unistd.h>
#include <pcap/pcap.h>
#include "packet_priv.h"
static void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
{
struct packet pkt;
packet_parse(&pkt, (const char *)bytes, h->caplen);
packet_print(&pkt);
}
static void usage(char *cmd)
{
printf("Usage: %s\n", cmd);
printf("Options:\n");
printf(" -f <pcap file> pcap file\n");
printf(" -h print help\n");
printf("\n");
}
int main(int argc, char **argv)
{
int opt = 0;
char *file = NULL;
while ((opt = getopt(argc, argv, "f:h")) != -1)
{
switch (opt)
{
case 'f':
file = optarg;
break;
case 'h':
usage(argv[0]);
return 0;
default:
usage(argv[0]);
return -1;
}
}
if (file == NULL)
{
usage(argv[0]);
return -1;
}
pcap_t *pcap = pcap_open_offline(file, NULL);
if (pcap == NULL)
{
printf("pcap_open_offline() failed\n");
return -1;
}
pcap_loop(pcap, -1, packet_handler, NULL);
pcap_close(pcap);
return 0;
}