diff --git a/include/stellar/packet.h b/include/stellar/packet.h index 9715b25..5fdd37c 100644 --- a/include/stellar/packet.h +++ b/include/stellar/packet.h @@ -14,33 +14,34 @@ enum layer_type LAYER_TYPE_ETHER = 1 << 0, LAYER_TYPE_PPP = 1 << 1, 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 - LAYER_TYPE_VLAN = 1 << 3, - LAYER_TYPE_PPPOE = 1 << 4, - LAYER_TYPE_MPLS = 1 << 5, + LAYER_TYPE_VLAN = 1 << 4, + LAYER_TYPE_PPPOE = 1 << 5, + LAYER_TYPE_MPLS = 1 << 6, LAYER_TYPE_L2_TUN = (LAYER_TYPE_VLAN | LAYER_TYPE_PPPOE | LAYER_TYPE_MPLS), // L3 -- network layer - LAYER_TYPE_IPV4 = 1 << 6, - LAYER_TYPE_IPV6 = 1 << 7, + LAYER_TYPE_IPV4 = 1 << 7, + LAYER_TYPE_IPV6 = 1 << 8, LAYER_TYPE_L3 = (LAYER_TYPE_IPV4 | LAYER_TYPE_IPV6), // L3 -- tunnel - LAYER_TYPE_GRE = 1 << 8, + LAYER_TYPE_GRE = 1 << 9, LAYER_TYPE_L3_TUN = (LAYER_TYPE_GRE), // L4 -- transport layer - LAYER_TYPE_UDP = 1 << 9, - LAYER_TYPE_TCP = 1 << 10, - LAYER_TYPE_ICMP = 1 << 11, - LAYER_TYPE_ICMP6 = 1 << 12, + LAYER_TYPE_UDP = 1 << 10, + LAYER_TYPE_TCP = 1 << 11, + LAYER_TYPE_ICMP = 1 << 12, + LAYER_TYPE_ICMP6 = 1 << 13, LAYER_TYPE_L4 = (LAYER_TYPE_UDP | LAYER_TYPE_TCP | LAYER_TYPE_ICMP | LAYER_TYPE_ICMP6), // L4 -- tunnel - LAYER_TYPE_VXLAN = 1 << 13, - LAYER_TYPE_GTPV1_U = 1 << 14, + LAYER_TYPE_VXLAN = 1 << 14, + LAYER_TYPE_GTPV1_U = 1 << 15, // 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), diff --git a/src/packet/packet.cpp b/src/packet/packet.cpp index e2e6e9e..6b81c3e 100644 --- a/src/packet/packet.cpp +++ b/src/packet/packet.cpp @@ -20,28 +20,28 @@ #define likely(expr) __builtin_expect((expr), 1) #define unlikely(expr) __builtin_expect((expr), 0) -#define PACKET_LOG_DATA_INSUFFICIENCY(type) \ - { \ - PACKET_LOG_ERROR("layer: %s, data insufficiency", \ - layer_type_to_str((type))); \ +#define PACKET_LOG_DATA_INSUFFICIENCY(type) \ + { \ + PACKET_LOG_WARN("layer: %s, data insufficiency", \ + layer_type_to_str((type))); \ } -#define PACKET_LOG_UNSUPPORT_PROTO(tag, next_proto) \ - { \ - PACKET_LOG_ERROR("%s: unsupport next proto %d", \ - (tag), (next_proto)); \ +#define PACKET_LOG_UNSUPPORT_PROTO(tag, next_proto) \ + { \ + PACKET_LOG_WARN("%s: unsupport next proto %d", \ + (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) \ +#define PACKET_LOG_UNSUPPORT_ETHPROTO(tag, next_proto) \ { \ - PACKET_LOG_ERROR("%s: unsupport next proto %d: %s", \ - (tag), (next_proto), ipproto_to_str(next_proto)); \ + PACKET_LOG_WARN("%s: unsupport next eth proto %d: %s", \ + (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_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_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_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"; case LAYER_TYPE_HDLC: return "HDLC"; + case LAYER_TYPE_L2TP: + return "L2TP"; case LAYER_TYPE_VLAN: return "VLAN"; case LAYER_TYPE_PPPOE: @@ -307,6 +314,10 @@ static inline const char *layer_type_to_str(enum layer_type type) return "UDP"; case LAYER_TYPE_TCP: return "TCP"; + case LAYER_TYPE_ICMP: + return "ICMP"; + case LAYER_TYPE_ICMP6: + return "ICMP6"; case LAYER_TYPE_VXLAN: return "VXLAN"; 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; } +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) { 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) { struct vlan_hdr @@ -742,7 +873,7 @@ static inline const char *parse_pppoe_ses(struct packet *pkt, const char *data, switch (next_proto) { - // TESTED + // TESTED case PPPOE_TYPE_IPV4: return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len); case PPPOE_TYPE_IPV6: @@ -882,7 +1013,7 @@ static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint1 // ip fragmented 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; return layer->pld_ptr; } @@ -910,11 +1041,13 @@ static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint1 // ipv6 fragment if (next_proto == IPPROTO_FRAGMENT) { - PACKET_LOG_DEBUG("ipv6 is fragmented"); + PACKET_LOG_WARN("ipv6 is fragmented"); pkt->frag_layer = layer; return layer->pld_ptr; } + // TODO parse ipv6 extension headers + // TESTED 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); } + 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; } @@ -1159,6 +1313,9 @@ static inline const char *parse_l4(struct packet *pkt, uint8_t next_proto, const // TESTED case IPPROTO_ICMPV6: return parse_icmp6(pkt, data, len); + case 115: + // L2TP + return parse_l2tpv3_over_ip(pkt, data, len); default: PACKET_LOG_UNSUPPORT_IPPROTO("l4", next_proto); return data; diff --git a/src/packet/test/gtest_packet.cpp b/src/packet/test/gtest_packet.cpp index dbf6efd..f2a4f36 100644 --- a/src/packet/test/gtest_packet.cpp +++ b/src/packet/test/gtest_packet.cpp @@ -4,7 +4,6 @@ #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] ****************************************************************************** * @@ -221,7 +220,6 @@ TEST(PACKET, ETH_VLAN_VLAN_IP4_IP4_UDP) #endif /****************************************************************************** - * Pcap file: 2-ETH_IP6_IP4_TCP_SSH.pcap * [Protocols in frame: eth:ethertype:ipv6:ip:tcp:ssh] ****************************************************************************** * @@ -447,7 +445,6 @@ TEST(PACKET, ETH_IP6_IP4_TCP_SSH) #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] ****************************************************************************** * @@ -730,7 +727,6 @@ TEST(PACKET, ETH_VLAN_IP6_IP4_GRE_PPP_IP4_UDP_DNS) #endif /****************************************************************************** - * Pcap file: 4-ETH_IP4_IP6_TCP.pcap * [Protocols in frame: eth:ethertype:ip:ipv6:tcp] ****************************************************************************** * @@ -929,7 +925,6 @@ TEST(PACKET, ETH_IP4_IP6_TCP) #endif /****************************************************************************** - * Pcap file: 5-ETH_IP6_IP6_UDP.pcap * [Protocols in frame: eth:ethertype:ipv6:ipv6:udp:data] ****************************************************************************** * @@ -1108,7 +1103,6 @@ TEST(PACKET, ETH_IP6_IP6_UDP) #endif /****************************************************************************** - * Pcap file: 6-ETH_MPLS_IP4_TCP.pcap * [Protocols in frame: eth:ethertype:mpls:ip:tcp] ****************************************************************************** * @@ -1306,7 +1300,6 @@ TEST(PACKET, ETH_MPLS_IP4_TCP) #endif /****************************************************************************** - * Pcap file: 7-ETH_MPLS_MPLS_IP4_TCP.pcap * [Protocols in frame: eth:ethertype:mpls:ip:tcp] ****************************************************************************** * @@ -1517,7 +1510,6 @@ TEST(PACKET, ETH_MPLS_MPLS_IP4_TCP) #endif /****************************************************************************** - * Pcap file: 8-ETH_VLAN_PPPOE_IP4_TCP.pcap * [Protocols in frame: eth:ethertype:vlan:ethertype:pppoes:ppp:ip:tcp] ****************************************************************************** * @@ -1739,7 +1731,6 @@ TEST(PACKET, ETH_VLAN_PPPOE_IP4_TCP) #endif /****************************************************************************** - * Pcap file: 9-ETH_IP6_UDP_GTP_IP6_TCP_TLS.pcap * [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 /****************************************************************************** - * Pcap file: 10-ETH_IP6_UDP_GTP_IP4_TCP_TLS.pcap * [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 /****************************************************************************** - * 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] ****************************************************************************** * @@ -2544,7 +2533,6 @@ TEST(PACKET, ETH_IP4_UDP_VXLAN_ETH_IP4_UDP_DNS) #endif /****************************************************************************** - * Pcap file: 12-ETH_MPLS_MPLS_PWETHCW_ETH_ARP.pcap * [Protocols in frame: eth:ethertype:mpls:pwethheuristic:pwethcw:eth:ethertype:arp] ****************************************************************************** * @@ -2954,6 +2942,223 @@ TEST(PACKET, ETH_IP6_ICMP6) } #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 TEST(PACKET, HASH_VALUE) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 73afe23..9c66832 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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) 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 ./pcap/ DESTINATION ./pcap/) \ No newline at end of file diff --git a/test/packet_parser.cpp b/test/packet_parser.cpp new file mode 100644 index 0000000..f1e55c6 --- /dev/null +++ b/test/packet_parser.cpp @@ -0,0 +1,57 @@ +#include +#include +#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\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; +} \ No newline at end of file