Restructure project and organize code.

This commit is contained in:
Christian Deacon
2025-02-22 09:50:57 -05:00
parent e3d47fda6f
commit 8756892791
25 changed files with 403 additions and 334 deletions

6
src/common/all.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include <common/config.h>
#include <common/constants.h>
#include <common/int_types.h>
#include <common/types.h>

12
src/common/config.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
// Feel free to comment this out if you don't want the `blocked` entry on the stats map to be incremented every single time a packet is dropped from the source IP being on the blocked map. Commenting this line out should increase performance when blocking malicious traffic.
#define DOSTATSONBLOCKMAP
// When this is defined, a check will occur inside the IPv4 and IPv6 filters. For IPv6 packets, if no IPv6 source/destination IP addresses are set, but there is an IPv4 address, it will ignore the filter. The same goes for IPv4, if there is no IPv4 source/destination IP addresses set, if an IPv6 address is set, it will ignore the filter.
#define ALLOWSINGLEIPV4V6
// If uncommented, rate limits for clients are determined using the source IP, port, and protocol instead of just the source IP.
// This allows for more precise rate limits (connection-specific instead of a single source IP).
// I decided not to include the destination IP/port because the source IP, port, and protocol should be represent a unique connection.
#define USE_FLOW_RL

7
src/common/constants.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#define MAX_PCKT_LENGTH 65535
#define MAX_FILTERS 60
#define MAX_TRACK_IPS 100000
#define MAX_CPUS 256
#define NANO_TO_SEC 1000000000

17
src/common/int_types.h Normal file
View File

@@ -0,0 +1,17 @@
#pragma once
#include <linux/types.h>
typedef __uint128_t u128;
typedef __u64 u64;
typedef __u32 u32;
typedef __u16 u16;
typedef __u8 u8;
typedef __s64 s64;
typedef __s32 s32;
typedef __s16 s16;
typedef __be64 be64;
typedef __be32 be32;
typedef __be16 be16;

134
src/common/types.h Normal file
View File

@@ -0,0 +1,134 @@
#pragma once
#include <common/int_types.h>
struct tcpopts
{
unsigned int enabled : 1;
unsigned int do_sport : 1;
u16 sport;
unsigned int do_dport : 1;
u16 dport;
// TCP flags.
unsigned int do_urg : 1;
unsigned int urg : 1;
unsigned int do_ack : 1;
unsigned int ack : 1;
unsigned int do_rst : 1;
unsigned int rst : 1;
unsigned int do_psh : 1;
unsigned int psh : 1;
unsigned int do_syn : 1;
unsigned int syn : 1;
unsigned int do_fin : 1;
unsigned int fin : 1;
unsigned int do_ece : 1;
unsigned int ece : 1;
unsigned int do_cwr : 1;
unsigned int cwr : 1;
};
struct udpopts
{
unsigned int enabled : 1;
unsigned int do_sport : 1;
u16 sport;
unsigned int do_dport : 1;
u16 dport;
};
struct icmpopts
{
unsigned int enabled : 1;
unsigned int do_code : 1;
u8 code;
unsigned int do_type : 1;
u8 type;
};
struct filter
{
u8 id;
unsigned int enabled : 1;
u8 action;
u32 src_ip;
u8 src_cidr;
u32 dst_ip;
u8 dst_cidr;
u32 src_ip6[4];
u32 dst_ip6[4];
unsigned int do_min_ttl : 1;
u8 min_ttl;
unsigned int do_max_ttl : 1;
u8 max_ttl;
unsigned int do_min_len : 1;
u16 min_len;
unsigned int do_max_len : 1;
u16 max_len;
unsigned int do_tos : 1;
u8 tos;
unsigned int do_pps : 1;
__u64 pps;
unsigned int do_bps : 1;
__u64 bps;
__u64 blocktime;
struct tcpopts tcpopts;
struct udpopts udpopts;
struct icmpopts icmpopts;
} __attribute__((__aligned__(8)));
struct stats
{
__u64 allowed;
__u64 dropped;
__u64 passed;
};
struct ip_stats
{
__u64 pps;
__u64 bps;
__u64 next_update;
};
struct flow
{
u32 ip;
u16 port;
u8 protocol;
};
struct flow6
{
u128 ip;
u16 port;
u8 protocol;
};

View File

@@ -20,12 +20,14 @@
#include <libbpf.h>
#include <xdp/libxdp.h>
#include <xdpfw.h>
#include <config.h>
#include <cmdline.h>
#include <common/all.h>
#include <loader/utils/cmdline.h>
#include <loader/utils/config.h>
#include <loader/utils/helpers.h>
// Other variables.
static __u8 cont = 1;
static u8 cont = 1;
static int filtersmap = -1;
static int statsmap = -1;
@@ -44,15 +46,15 @@ void SignalHndl(int tmp)
void UpdateFilters(struct config *cfg)
{
// Loop through all filters and delete the map. We do this in the case rules were edited and were put out of order since the key doesn't uniquely map to a specific rule.
for (__u8 i = 0; i < MAX_FILTERS; i++)
for (u8 i = 0; i < MAX_FILTERS; i++)
{
__u32 key = i;
u32 key = i;
bpf_map_delete_elem(filtersmap, &key);
}
// Add a filter to the filter maps.
for (__u32 i = 0; i < MAX_FILTERS; i++)
for (u32 i = 0; i < MAX_FILTERS; i++)
{
// Check if we have a valid ID.
if (cfg->filters[i].id < 1)
@@ -96,7 +98,7 @@ int UpdateConfig(struct config *cfg, char *cfgfile)
SetCfgDefaults(cfg);
for (__u16 i = 0; i < MAX_FILTERS; i++)
for (u16 i = 0; i < MAX_FILTERS; i++)
{
cfg->filters[i] = (struct filter) {0};
}
@@ -178,11 +180,11 @@ struct xdp_program *LoadBpfObj(const char *filename)
*
* @return 0 on success and 1 on error.
*/
int AttachXdp(struct xdp_program *prog, int ifidx, __u8 detach, struct cmdline *cmd)
int AttachXdp(struct xdp_program *prog, int ifidx, u8 detach, struct cmdline *cmd)
{
int err;
__u32 mode = XDP_MODE_NATIVE;
u32 mode = XDP_MODE_NATIVE;
char *smode;
smode = "DRV/native";
@@ -199,7 +201,7 @@ int AttachXdp(struct xdp_program *prog, int ifidx, __u8 detach, struct cmdline *
mode = XDP_MODE_SKB;
}
__u8 exit = 0;
u8 exit = 0;
while (!exit)
{
@@ -427,7 +429,7 @@ int main(int argc, char *argv[])
}
// XDP variables.
const char *filename = "/etc/xdpfw/xdpfw_kern.o";
const char *filename = "/etc/xdpfw/xdp_prog.o";
// Load BPF object.
struct xdp_program *prog = LoadBpfObj(filename);
@@ -518,7 +520,7 @@ int main(int argc, char *argv[])
// Update stats.
if (!cfg.nostats)
{
__u32 key = 0;
u32 key = 0;
struct stats stats[MAX_CPUS];
//memset(stats, 0, sizeof(struct stats) * MAX_CPUS);

View File

@@ -1,14 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <libconfig.h>
#include <string.h>
#include <linux/types.h>
#include <loader/utils/config.h>
#include <arpa/inet.h>
#include <xdpfw.h>
#include <config.h>
#include <utils.h>
#include <loader/utils/helpers.h>
FILE *file;
@@ -26,7 +18,7 @@ void SetCfgDefaults(struct config *cfg)
cfg->nostats = 0;
cfg->stdout_update_time = 1000;
for (__u16 i = 0; i < MAX_FILTERS; i++)
for (u16 i = 0; i < MAX_FILTERS; i++)
{
cfg->filters[i].id = 0;
cfg->filters[i].enabled = 0;
@@ -34,7 +26,7 @@ void SetCfgDefaults(struct config *cfg)
cfg->filters[i].src_ip = 0;
cfg->filters[i].dst_ip = 0;
for (__u8 j = 0; j < 4; j++)
for (u8 j = 0; j < 4; j++)
{
cfg->filters[i].src_ip6[j] = 0;
cfg->filters[i].dst_ip6[j] = 0;
@@ -197,7 +189,7 @@ int ReadCfg(struct config *cfg)
// Set filter count.
int filters = 0;
for (__u8 i = 0; i < config_setting_length(setting); i++)
for (u8 i = 0; i < config_setting_length(setting); i++)
{
config_setting_t* filter = config_setting_get_elem(setting, i);
@@ -259,7 +251,7 @@ int ReadCfg(struct config *cfg)
inet_pton(AF_INET6, sip6, &in);
for (__u8 j = 0; j < 4; j++)
for (u8 j = 0; j < 4; j++)
{
cfg->filters[i].src_ip6[j] = in.__in6_u.__u6_addr32[j];
}
@@ -274,7 +266,7 @@ int ReadCfg(struct config *cfg)
inet_pton(AF_INET6, dip6, &in);
for (__u8 j = 0; j < 4; j++)
for (u8 j = 0; j < 4; j++)
{
cfg->filters[i].dst_ip6[j] = in.__in6_u.__u6_addr32[j];
}
@@ -285,7 +277,7 @@ int ReadCfg(struct config *cfg)
if (config_setting_lookup_int(filter, "min_ttl", &min_ttl))
{
cfg->filters[i].min_ttl = (__u8)min_ttl;
cfg->filters[i].min_ttl = (u8)min_ttl;
cfg->filters[i].do_min_ttl = 1;
}
@@ -294,7 +286,7 @@ int ReadCfg(struct config *cfg)
if (config_setting_lookup_int(filter, "max_ttl", &max_ttl))
{
cfg->filters[i].max_ttl = (__u8)max_ttl;
cfg->filters[i].max_ttl = (u8)max_ttl;
cfg->filters[i].do_max_ttl = 1;
}
@@ -321,7 +313,7 @@ int ReadCfg(struct config *cfg)
if (config_setting_lookup_int(filter, "tos", &tos))
{
cfg->filters[i].tos = (__u8)tos;
cfg->filters[i].tos = (u8)tos;
cfg->filters[i].do_tos = 1;
}
@@ -369,7 +361,7 @@ int ReadCfg(struct config *cfg)
if (config_setting_lookup_int64(filter, "tcp_sport", &tcpsport))
{
cfg->filters[i].tcpopts.sport = (__u16)tcpsport;
cfg->filters[i].tcpopts.sport = (u16)tcpsport;
cfg->filters[i].tcpopts.do_sport = 1;
}
@@ -378,7 +370,7 @@ int ReadCfg(struct config *cfg)
if (config_setting_lookup_int64(filter, "tcp_dport", &tcpdport))
{
cfg->filters[i].tcpopts.dport = (__u16)tcpdport;
cfg->filters[i].tcpopts.dport = (u16)tcpdport;
cfg->filters[i].tcpopts.do_dport = 1;
}
@@ -469,7 +461,7 @@ int ReadCfg(struct config *cfg)
if (config_setting_lookup_int64(filter, "udp_sport", &udpsport))
{
cfg->filters[i].udpopts.sport = (__u16)udpsport;
cfg->filters[i].udpopts.sport = (u16)udpsport;
cfg->filters[i].udpopts.do_sport = 1;
}
@@ -478,7 +470,7 @@ int ReadCfg(struct config *cfg)
if (config_setting_lookup_int64(filter, "udp_dport", &udpdport))
{
cfg->filters[i].udpopts.dport = (__u16)udpdport;
cfg->filters[i].udpopts.dport = (u16)udpdport;
cfg->filters[i].udpopts.do_dport = 1;
}
@@ -496,7 +488,7 @@ int ReadCfg(struct config *cfg)
if (config_setting_lookup_int(filter, "icmp_code", &icmpcode))
{
cfg->filters[i].icmpopts.code = (__u8)icmpcode;
cfg->filters[i].icmpopts.code = (u8)icmpcode;
cfg->filters[i].icmpopts.do_code = 1;
}
@@ -505,7 +497,7 @@ int ReadCfg(struct config *cfg)
if (config_setting_lookup_int(filter, "icmp_type", &icmptype))
{
cfg->filters[i].icmpopts.type = (__u8)icmptype;
cfg->filters[i].icmpopts.type = (u8)icmptype;
cfg->filters[i].icmpopts.do_type = 1;
}

View File

@@ -1,13 +1,19 @@
#pragma once
#include <common/all.h>
#include <stdio.h>
#include <stdlib.h>
#include <libconfig.h>
#include <string.h>
#include <linux/types.h>
#include "xdpfw.h"
#include <arpa/inet.h>
struct config
{
char *interface;
__u16 updatetime;
u16 updatetime;
unsigned int nostats : 1;
int stdout_update_time;
struct filter filters[MAX_FILTERS];

View File

@@ -1,16 +1,4 @@
#pragma once
#include <linux/types.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
struct ip
{
__u32 ip;
__u32 cidr;
};
#include <loader/utils/helpers.h>
/**
* Parses an IP string with CIDR support. Stores IP in network byte order in ip.ip and CIDR in ip.cidr.

View File

@@ -0,0 +1,16 @@
#pragma once
#include <common/all.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
struct ip
{
u32 ip;
u32 cidr;
};
struct ip ParseIp(const char *ip);

View File

@@ -1,8 +0,0 @@
#pragma once
#include <linux/bpf.h>
#include <linux/bpf_common.h>
#include <bpf_helpers.h>
#include <xdp/xdp_helpers.h>
#include <xdp/prog_dispatcher.h>

View File

@@ -8,13 +8,12 @@
#include <linux/in.h>
#include <stdatomic.h>
#include <xdp/helpers.h>
#include <common/all.h>
#include <xdpfw.h>
#include <xdp/utils/rl.h>
#include <xdp/utils/helpers.h>
#include <xdp/maps.h>
#include <xdp/rl.h>
#include <xdp/utils.h>
#include <xdp/utils/maps.h>
SEC("xdp_prog")
int xdp_prog_main(struct xdp_md *ctx)
@@ -38,13 +37,13 @@ int xdp_prog_main(struct xdp_md *ctx)
return XDP_PASS;
}
__u8 action = 0;
u8 action = 0;
__u64 blocktime = 1;
// Initialize IP headers.
struct iphdr *iph = NULL;
struct ipv6hdr *iph6 = NULL;
__u128 src_ip6 = 0;
u128 src_ip6 = 0;
// Set IPv4 and IPv6 common variables.
if (eth->h_proto == htons(ETH_P_IPV6))
@@ -75,7 +74,7 @@ int xdp_prog_main(struct xdp_md *ctx)
}
// Get stats map.
__u32 key = 0;
u32 key = 0;
struct stats *stats = bpf_map_lookup_elem(&stats_map, &key);
__u64 now = bpf_ktime_get_ns();
@@ -122,7 +121,7 @@ int xdp_prog_main(struct xdp_md *ctx)
}
// Retrieve total packet length.
__u16 pkt_len = data_end - data;
u16 pkt_len = data_end - data;
// Parse layer-4 headers and determine source port and protocol.
struct tcphdr *tcph = NULL;
@@ -130,8 +129,8 @@ int xdp_prog_main(struct xdp_md *ctx)
struct icmphdr *icmph = NULL;
struct icmp6hdr *icmp6h = NULL;
__u16 src_port = 0;
__u8 protocol = 0;
u16 src_port = 0;
u8 protocol = 0;
if (iph6)
{
@@ -241,9 +240,9 @@ int xdp_prog_main(struct xdp_md *ctx)
UpdateIpStats(&pps, &bps, iph->saddr, src_port, protocol, pkt_len, now);
}
for (__u8 i = 0; i < MAX_FILTERS; i++)
for (u8 i = 0; i < MAX_FILTERS; i++)
{
__u32 key = i;
u32 key = i;
struct filter *filter = bpf_map_lookup_elem(&filters_map, &key);

View File

@@ -1,13 +1,4 @@
#pragma once
#include <xdpfw.h>
#include <xdp/maps.h>
#include <xdp/helpers.h>
#ifndef memcpy
#define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n))
#endif
#include <xdp/utils/helpers.h>
/**
* Checks if an IP is within a specific CIDR range.
@@ -18,7 +9,7 @@
*
* @return 1 on yes, 0 on no.
*/
static __always_inline __u8 IsIpInRange(__u32 src_ip, __u32 net_ip, __u8 cidr)
static __always_inline u8 IsIpInRange(u32 src_ip, u32 net_ip, u8 cidr)
{
return !((src_ip ^ net_ip) & htonl(0xFFFFFFFFu << (32 - cidr)));
}

33
src/xdp/utils/helpers.h Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
#include <common/all.h>
#include <linux/bpf.h>
#include <linux/bpf_common.h>
#include <bpf_helpers.h>
#include <xdp/xdp_helpers.h>
#include <xdp/prog_dispatcher.h>
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define htons(x) ((__be16)___constant_swab16((x)))
#define ntohs(x) ((__be16)___constant_swab16((x)))
#define htonl(x) ((__be32)___constant_swab32((x)))
#define ntohl(x) ((__be32)___constant_swab32((x)))
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define htons(x) (x)
#define ntohs(X) (x)
#define htonl(x) (x)
#define ntohl(x) (x)
#endif
#ifndef memcpy
#define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n))
#endif
static __always_inline u8 IsIpInRange(u32 src_ip, u32 net_ip, u8 cidr);
#include "helpers.c"

View File

@@ -1,8 +1,9 @@
#pragma once
#include <xdpfw.h>
#include <common/int_types.h>
#include <common/types.h>
#include <xdp/helpers.h>
#include <xdp/utils/helpers.h>
struct
{
@@ -14,7 +15,7 @@ struct
{
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__uint(max_entries, MAX_FILTERS);
__type(key, __u32);
__type(key, u32);
__type(value, struct filter);
} filters_map SEC(".maps");
@@ -22,7 +23,7 @@ struct
{
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__uint(max_entries, 1);
__type(key, __u32);
__type(key, u32);
__type(value, struct stats);
} stats_map SEC(".maps");
@@ -33,7 +34,7 @@ struct
#ifdef USE_FLOW_RL
__type(key, struct flow);
#else
__type(key, __u32);
__type(key, u32);
#endif
__type(value, struct ip_stats);
} ip_stats_map SEC(".maps");
@@ -42,7 +43,7 @@ struct
{
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__uint(max_entries, MAX_TRACK_IPS);
__type(key, __u32);
__type(key, u32);
__type(value, __u64);
} ip_blacklist_map SEC(".maps");
@@ -53,7 +54,7 @@ struct
#ifdef USE_FLOW_RL
__type(key, struct flow6);
#else
__type(key, __u128);
__type(key, u128);
#endif
__type(value, struct ip_stats);
} ip6_stats_map SEC(".maps");
@@ -62,6 +63,6 @@ struct
{
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__uint(max_entries, MAX_TRACK_IPS);
__type(key, __u128);
__type(key, u128);
__type(value, __u64);
} ip6_blacklist_map SEC(".maps");

View File

@@ -1,9 +1,4 @@
#pragma once
#include <xdpfw.h>
#include <xdp/maps.h>
#include <xdp/helpers.h>
#include <xdp/utils/rl.h>
/**
* Updates IPv4 client stats.
@@ -18,7 +13,7 @@
*
* @return void
*/
static __always_inline void UpdateIpStats(__u64 *pps, __u64 *bps, __u32 ip, __u16 port, __u8 protocol, __u16 pkt_len, __u64 now)
static __always_inline void UpdateIpStats(__u64 *pps, __u64 *bps, u32 ip, u16 port, u8 protocol, u16 pkt_len, __u64 now)
{
#ifdef USE_FLOW_RL
struct flow key = {0};
@@ -83,7 +78,7 @@ static __always_inline void UpdateIpStats(__u64 *pps, __u64 *bps, __u32 ip, __u1
*
* @return void
*/
static __always_inline void UpdateIp6Stats(__u64 *pps, __u64 *bps, __u128 *ip, __u16 port, __u8 protocol, __u16 pkt_len, __u64 now)
static __always_inline void UpdateIp6Stats(__u64 *pps, __u64 *bps, u128 *ip, u16 port, u8 protocol, u16 pkt_len, __u64 now)
{
#ifdef USE_FLOW_RL
struct flow6 key = {0};

12
src/xdp/utils/rl.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include <common/all.h>
#include <xdp/utils/helpers.h>
#include <xdp/utils/maps.h>
static __always_inline void UpdateIpStats(__u64 *pps, __u64 *bps, u32 ip, u16 port, u8 protocol, u16 pkt_len, __u64 now);
static __always_inline void UpdateIp6Stats(__u64 *pps, __u64 *bps, u128 *ip, u16 port, u8 protocol, u16 pkt_len, __u64 now);
#include "rl.c"

View File

@@ -1,172 +0,0 @@
#pragma once
#include <linux/types.h>
#define MAX_PCKT_LENGTH 65535
#define MAX_FILTERS 60
#define MAX_TRACK_IPS 100000
#define MAX_CPUS 256
#define NANO_TO_SEC 1000000000
#define __u128 __uint128_t
// Additional options for XDP program.
//#define DEBUG
// Feel free to comment this out if you don't want the `blocked` entry on the stats map to be incremented every single time a packet is dropped from the source IP being on the blocked map. Commenting this line out should increase performance when blocking malicious traffic.
#define DOSTATSONBLOCKMAP
// When this is defined, a check will occur inside the IPv4 and IPv6 filters. For IPv6 packets, if no IPv6 source/destination IP addresses are set, but there is an IPv4 address, it will ignore the filter. The same goes for IPv4, if there is no IPv4 source/destination IP addresses set, if an IPv6 address is set, it will ignore the filter.
#define ALLOWSINGLEIPV4V6
// If uncommented, rate limits for clients are determined using the source IP, port, and protocol instead of just the source IP.
// This allows for more precise rate limits (connection-specific instead of a single source IP).
// I decided not to include the destination IP/port because the source IP, port, and protocol should be represent a unique connection.
#define USE_FLOW_RL
#ifdef __BPF__
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define htons(x) ((__be16)___constant_swab16((x)))
#define ntohs(x) ((__be16)___constant_swab16((x)))
#define htonl(x) ((__be32)___constant_swab32((x)))
#define ntohl(x) ((__be32)___constant_swab32((x)))
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define htons(x) (x)
#define ntohs(X) (x)
#define htonl(x) (x)
#define ntohl(x) (x)
#endif
#endif
struct tcpopts
{
unsigned int enabled : 1;
unsigned int do_sport : 1;
__u16 sport;
unsigned int do_dport : 1;
__u16 dport;
// TCP flags.
unsigned int do_urg : 1;
unsigned int urg : 1;
unsigned int do_ack : 1;
unsigned int ack : 1;
unsigned int do_rst : 1;
unsigned int rst : 1;
unsigned int do_psh : 1;
unsigned int psh : 1;
unsigned int do_syn : 1;
unsigned int syn : 1;
unsigned int do_fin : 1;
unsigned int fin : 1;
unsigned int do_ece : 1;
unsigned int ece : 1;
unsigned int do_cwr : 1;
unsigned int cwr : 1;
};
struct udpopts
{
unsigned int enabled : 1;
unsigned int do_sport : 1;
__u16 sport;
unsigned int do_dport : 1;
__u16 dport;
};
struct icmpopts
{
unsigned int enabled : 1;
unsigned int do_code : 1;
__u8 code;
unsigned int do_type : 1;
__u8 type;
};
struct filter
{
__u8 id;
unsigned int enabled : 1;
__u8 action;
__u32 src_ip;
__u8 src_cidr;
__u32 dst_ip;
__u8 dst_cidr;
__u32 src_ip6[4];
__u32 dst_ip6[4];
unsigned int do_min_ttl : 1;
__u8 min_ttl;
unsigned int do_max_ttl : 1;
__u8 max_ttl;
unsigned int do_min_len : 1;
__u16 min_len;
unsigned int do_max_len : 1;
__u16 max_len;
unsigned int do_tos : 1;
int8_t tos;
unsigned int do_pps : 1;
__u64 pps;
unsigned int do_bps : 1;
__u64 bps;
__u64 blocktime;
struct tcpopts tcpopts;
struct udpopts udpopts;
struct icmpopts icmpopts;
} __attribute__((__aligned__(8)));
struct stats
{
__u64 allowed;
__u64 dropped;
__u64 passed;
};
struct ip_stats
{
__u64 pps;
__u64 bps;
__u64 next_update;
};
struct flow
{
__u32 ip;
__u16 port;
__u8 protocol;
};
struct flow6
{
__u128 ip;
__u16 port;
__u8 protocol;
};