#pragma once #ifdef __cplusplus extern "C" { #endif #include #define __FAVOR_BSD 1 #include #include #include #include #include #include #include #include struct packet; /****************************************************************************** * layer ******************************************************************************/ 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 // } /****************************************************************************** * tunnel ******************************************************************************/ enum tunnel_type { TUNNEL_IPV4 = 1, // contain layers: IPv4, (next inner layer must be IPv4 / IPv6) TUNNEL_IPV6 = 2, // contain layers: IPv6, (next inner layer must be IPv4 / IPv6) TUNNEL_GRE = 3, // contain layers: IPv4 + GRE // contain layers: IPv6 + GRE TUNNEL_GTP = 4, // contain layers: IPv4 + UDP + GTP // contain layers: IPv6 + UDP + GTP TUNNEL_VXLAN = 5, // contain layers: IPv4 + UDP + VXLAN // contain layers: IPv6 + UDP + VXLAN TUNNEL_L2TP = 6, // contain layers: IPv4 + UDP + L2TP // contain layers: IPv6 + UDP + L2TP TUNNEL_TEREDO = 7, // contain layers: IPv4 + UDP, (next inner layer must be IPv6) }; #define MAX_LAYERS_PER_TUNNEL 3 struct tunnel { enum tunnel_type type; int layer_count; const struct layer *layers[MAX_LAYERS_PER_TUNNEL]; }; int packet_get_tunnel_count(const struct packet *pkt); // return 0: success  // return -1: failed int packet_get_tunnel_by_idx(const struct packet *pkt, int idx, struct tunnel *out); /****************************************************************************** * build ******************************************************************************/ /* * tcp_seq: the sequence number of the new TCP packet (in host byte order) * tcp_ack: the acknowledgment number of the new TCP packet (in host byte order) * tcp_options_len: the length of the options (must be a multiple of 4) */ struct packet *packet_build_tcp(const struct packet *origin_pkt, uint32_t tcp_seq, uint32_t tcp_ack, uint8_t tcp_flags, const char *tcp_options, uint16_t tcp_options_len, const char *tcp_payload, uint16_t tcp_payload_len); struct packet *packet_build_udp(const struct packet *origin_pkt, const char *udp_payload, uint16_t udp_payload_len); struct packet *packet_build_l3(const struct packet *origin_pkt, uint8_t ip_proto, const char *l3_payload, uint16_t l3_payload_len); /****************************************************************************** * utils ******************************************************************************/ #define MAX_SIDS 8 struct sids { uint16_t sid[MAX_SIDS]; int used; }; void packet_prepend_sids(struct packet *pkt, const struct sids *sids); enum packet_direction { PACKET_DIRECTION_OUTGOING = 0, // Internal -> External: 0 PACKET_DIRECTION_INCOMING = 1, // External -> Internal: 1 }; enum packet_direction packet_get_direction(const struct packet *pkt); enum packet_action { PACKET_ACTION_FORWARD = 0, PACKET_ACTION_DROP = 1, }; void packet_set_action(struct packet *pkt, enum packet_action action); enum packet_action packet_get_action(const struct packet *pkt); void packet_set_timeval(struct packet *pkt, const struct timeval *tv); const struct timeval *packet_get_timeval(const struct packet *pkt); const char *packet_get_raw_data(const struct packet *pkt); uint16_t packet_get_raw_len(const struct packet *pkt); const char *packet_get_payload(const struct packet *pkt); uint16_t packet_get_payload_len(const struct packet *pkt); void packet_set_exdata(struct packet *pkt, int idx, void *ex_ptr); void *packet_get_exdata(struct packet *pkt, int idx); #ifdef __cplusplus } #endif