#pragma once #ifdef __cplusplus extern "C" { #endif #define __FAVOR_BSD 1 #include #include #include #include #include #include #include #include enum layer_proto { LAYER_PROTO_NONE = 0, // L2 -- data link layer LAYER_PROTO_ETHER = 1, LAYER_PROTO_PWETH = 2, LAYER_PROTO_PPP = 3, LAYER_PROTO_L2TP = 4, // L2 -- tunnel LAYER_PROTO_VLAN = 21, LAYER_PROTO_PPPOE = 22, LAYER_PROTO_MPLS = 23, // L3 -- network layer LAYER_PROTO_IPV4 = 31, LAYER_PROTO_IPV6 = 32, LAYER_PROTO_IPAH = 33, // L3 -- tunnel LAYER_PROTO_GRE = 41, // L4 -- transport layer LAYER_PROTO_UDP = 51, LAYER_PROTO_TCP = 52, LAYER_PROTO_ICMP = 53, LAYER_PROTO_ICMP6 = 54, // L4 -- tunnel LAYER_PROTO_VXLAN = 61, LAYER_PROTO_GTP_U = 62, LAYER_PROTO_GTP_C = 63, }; struct layer { enum layer_proto proto; uint16_t hdr_len; union { // all hdr ptr refer to raw packet, read-only const struct ethhdr *eth; const struct ip *ip4; const struct ip6_hdr *ip6; const struct tcphdr *tcp; const struct udphdr *udp; const struct icmphdr *icmp4; const struct icmp6_hdr *icmp6; const struct mpls_label *mpls; const char *raw; // e.g. pppoe, l2tp, gre, gtp, etc. } hdr; }; int packet_get_layer_count(const struct packet *pkt); const struct layer *packet_get_layer_by_idx(const struct packet *pkt, int idx); // // example: foreach layer in packet (inorder) // int count = packet_get_layer_count(pkt); // for (int i = 0; i < count; i++) // { // const struct layer *layer = packet_get_layer_by_idx(pkt, i); // // do something with layer // } // // // // example: foreach layer in packet (reverse) // int count = packet_get_layer_count(pkt); // for (int i = count - 1; i >= 0; i--) // { // const struct layer *layer = packet_get_layer_by_idx(pkt, i); // // do something with layer // } #ifdef __cplusplus } #endif