packet parser support L2TPv2
This commit is contained in:
@@ -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),
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
57
test/packet_parser.cpp
Normal 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user