#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 = 62, }; struct layer { enum layer_proto proto; uint16_t hdr_len; union { struct ethhdr *eth; struct ip *ip4; struct ip6_hdr *ip6; struct tcphdr *tcp; struct udphdr *udp; struct icmphdr *icmp4; struct icmp6_hdr *icmp6; struct mpls_label *mpls; char *raw; } hdr; }; int packet_get_layer_count(const struct packet *pkt); // return 0: success  // return -1: failed int packet_get_layer_by_idx(const struct packet *pkt, int idx, struct layer *out); #define PACKET_FOREACH_LAYER_INORDER(pkt, layer) \ for (int i = 0; i < packet_get_layer_count(pkt) && packet_get_layer_by_idx(pkt, i, &layer) == 0; i++) #define PACKET_FOREACH_LAYER_REVERSE(pkt, layer) \ for (int i = packet_get_layer_count(pkt) - 1; i >= 0 && packet_get_layer_by_idx(pkt, i, &layer) == 0; i--) #define PACKET_GETALL_LAYERS(pkt, layers) \ { \ int num = MIN(packet_get_layer_count(pkt), (sizeof(layers) / sizeof(layers[0]))); \ for (int i = 0; i < num && packet_get_layer_by_idx(pkt, i, &layers[i]) == 0; i++) \ /* void */; \ return num; \ } #ifdef __cplusplus } #endif