Improved config and added additional functionality.

This commit is contained in:
Christian Deacon
2020-05-05 23:58:34 +00:00
parent 5a2589b178
commit f88a52f792
3 changed files with 122 additions and 50 deletions

View File

@@ -17,21 +17,44 @@ void SetConfigDefaults(struct config_map *cfg)
for (uint16_t i = 0; i < MAX_FILTERS; i++)
{
cfg->filters[i].id = 0;
cfg->filters[i].enabled = 0;
cfg->filters[i].action = 0;
cfg->filters[i].srcIP = 0;
cfg->filters[i].dstIP = 0;
cfg->filters[i].min_id = 0;
cfg->filters[i].max_id = 4294967295;
cfg->filters[i].do_min_len = 0;
cfg->filters[i].min_len = 0;
cfg->filters[i].do_max_len = 0;
cfg->filters[i].max_len = 65535;
cfg->filters[i].do_min_ttl = 0;
cfg->filters[i].min_ttl = 0;
cfg->filters[i].do_max_ttl = 0;
cfg->filters[i].max_ttl = 255;
cfg->filters[i].do_tos = 0;
cfg->filters[i].tos = 0;
cfg->filters[i].tcpopts.enabled = 0;
cfg->filters[i].tcpopts.do_dport = 0;
cfg->filters[i].tcpopts.do_dport = 0;
cfg->filters[i].tcpopts.do_urg = 0;
cfg->filters[i].tcpopts.do_ack = 0;
cfg->filters[i].tcpopts.do_rst = 0;
cfg->filters[i].tcpopts.do_psh = 0;
cfg->filters[i].tcpopts.do_syn = 0;
cfg->filters[i].tcpopts.do_fin = 0;
cfg->filters[i].udpopts.enabled = 0;
cfg->filters[i].udpopts.do_sport = 0;
cfg->filters[i].udpopts.do_dport = 0;
cfg->filters[i].icmpopts.enabled = 0;
cfg->filters[i].icmpopts.do_code = 0;
cfg->filters[i].icmpopts.do_type = 0;
for (uint16_t j = 0; j < MAX_PCKT_LENGTH - 1; j++)
{
@@ -184,6 +207,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(filter, "min_ttl", &min_ttl))
{
cfg->filters[i].min_ttl = (uint8_t)min_ttl;
cfg->filters[i].do_min_ttl = 1;
}
// Maximum TTL (not required).
@@ -192,6 +216,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(filter, "max_ttl", &max_ttl))
{
cfg->filters[i].max_ttl = (uint8_t)max_ttl;
cfg->filters[i].do_max_ttl = 1;
}
// Minimum length (not required).
@@ -200,6 +225,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(filter, "min_len", &min_len))
{
cfg->filters[i].min_len = min_len;
cfg->filters[i].do_min_len = 1;
}
// Maximum length (not required).
@@ -208,6 +234,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(filter, "max_len", &max_len))
{
cfg->filters[i].max_len = max_len;
cfg->filters[i].do_max_len = 1;
}
// TOS (not required).
@@ -216,6 +243,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(filter, "tos", &tos))
{
cfg->filters[i].tos = (uint8_t)tos;
cfg->filters[i].do_tos = 1;
}
// Payload match.
@@ -265,6 +293,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int64(tcp, "sport", &sport))
{
cfg->filters[i].tcpopts.sport = (uint16_t)sport;
cfg->filters[i].tcpopts.do_sport = 1;
}
// Destination port.
@@ -273,6 +302,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int64(tcp, "dport", &dport))
{
cfg->filters[i].tcpopts.dport = (uint16_t)dport;
cfg->filters[i].tcpopts.do_dport = 1;
}
// URG flag.
@@ -281,6 +311,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_bool(tcp, "urg", &urg))
{
cfg->filters[i].tcpopts.urg = urg;
cfg->filters[i].tcpopts.do_urg = 1;
}
// ACK flag.
@@ -289,6 +320,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_bool(tcp, "ack", &ack))
{
cfg->filters[i].tcpopts.ack = ack;
cfg->filters[i].tcpopts.do_ack = 1;
}
// RST flag.
@@ -297,6 +329,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_bool(tcp, "rst", &rst))
{
cfg->filters[i].tcpopts.rst = rst;
cfg->filters[i].tcpopts.do_rst = 1;
}
// PSH flag.
@@ -305,6 +338,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_bool(tcp, "psh", &psh))
{
cfg->filters[i].tcpopts.psh = psh;
cfg->filters[i].tcpopts.do_psh = 1;
}
// SYN flag.
@@ -313,6 +347,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_bool(tcp, "syn", &syn))
{
cfg->filters[i].tcpopts.syn = syn;
cfg->filters[i].tcpopts.do_syn = 1;
}
// FIN flag.
@@ -321,6 +356,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_bool(tcp, "fin", &fin))
{
cfg->filters[i].tcpopts.fin = fin;
cfg->filters[i].tcpopts.do_fin = 1;
}
}
}
@@ -349,6 +385,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int64(udp, "sport", &sport))
{
cfg->filters[i].udpopts.sport = (uint16_t)sport;
cfg->filters[i].udpopts.do_sport = 1;
}
// Destination port.
@@ -357,6 +394,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int64(udp, "dport", &dport))
{
cfg->filters[i].udpopts.dport = (uint16_t)dport;
cfg->filters[i].udpopts.do_dport = 1;
}
}
}
@@ -385,6 +423,7 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(icmp, "code", &code))
{
cfg->filters[i].icmpopts.code = (uint8_t)code;
cfg->filters[i].icmpopts.do_code = 1;
}
// ICMP type.
@@ -393,10 +432,14 @@ int ReadConfig(struct config_map *cfg)
if (config_setting_lookup_int(icmp, "type", &type))
{
cfg->filters[i].icmpopts.type = (uint8_t)type;
cfg->filters[i].icmpopts.do_type = 1;
}
}
}
// Assign ID.
cfg->filters[i].id = filters + 1;
// Increase filter count.
filters++;
}

View File

@@ -4,21 +4,35 @@
#include <inttypes.h>
#define MAX_PCKT_LENGTH 65535
#define MAX_FILTERS 255
#define MAX_FILTERS 50
struct tcpopts
{
unsigned int enabled : 1;
unsigned int do_sport : 1;
uint16_t sport;
unsigned int do_dport : 1;
uint16_t 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;
};
@@ -26,7 +40,10 @@ struct udpopts
{
unsigned int enabled : 1;
unsigned int do_sport : 1;
uint16_t sport;
unsigned int do_dport : 1;
uint16_t dport;
};
@@ -34,12 +51,17 @@ struct icmpopts
{
unsigned int enabled : 1;
unsigned int do_code : 1;
uint8_t code;
unsigned int do_type : 1;
uint8_t type;
};
struct filter
{
uint8_t id;
unsigned int enabled : 1;
uint8_t action;
@@ -47,15 +69,19 @@ struct filter
uint32_t srcIP;
uint32_t dstIP;
unsigned int do_min_ttl : 1;
uint8_t min_ttl;
unsigned int do_max_ttl : 1;
uint8_t max_ttl;
unsigned int do_min_len : 1;
uint16_t min_len;
unsigned int do_max_len : 1;
uint16_t max_len;
uint32_t min_id;
uint32_t max_id;
unsigned int do_tos : 1;
int8_t tos;
uint8_t payloadMatch[MAX_PCKT_LENGTH];
@@ -66,4 +92,11 @@ struct filter
struct icmpopts icmpopts;
};
struct xdpfw_stats
{
uint64_t allowed;
uint64_t blocked;
};
#endif

View File

@@ -35,6 +35,7 @@ const struct option opts[] =
static uint8_t cont = 1;
static int filter_map_fd = -1;
static int count_map_fd = -1;
static int stats_map_fd = -1;
void signalHndl(int tmp)
{
@@ -78,18 +79,17 @@ void parse_command_line(int argc, char *argv[])
void update_BPF(struct config_map *conf)
{
// Loop through all filters and delete the map.
for (uint32_t i = 0; i < MAX_FILTERS; i++)
for (uint8_t i = 0; i < MAX_FILTERS; i++)
{
if (bpf_map_delete_elem(filter_map_fd, &i) != 0)
{
fprintf(stderr, "Error deleting BPF item #%d\n", i);
}
uint32_t key = i;
bpf_map_delete_elem(filter_map_fd, &key);
}
// Add a filter to the filter maps.
for (uint32_t i = 0; i < conf->filterCount; i++)
{
if (bpf_map_update_elem(filter_map_fd, &i, &conf->filters[i], BPF_ANY))
if (bpf_map_update_elem(filter_map_fd, &i, &conf->filters[i], BPF_ANY) == -1)
{
fprintf(stderr, "Error updating BPF item #%d\n", i);
}
@@ -162,6 +162,7 @@ int load_bpf_object_file__simple(const char *filename)
filter_map_fd = find_map_fd(obj, "filters_map");
count_map_fd = find_map_fd(obj, "count_map");
stats_map_fd = find_map_fd(obj, "stats_map");
return first_prog_fd;
}
@@ -254,38 +255,6 @@ static int xdp_attach(int ifindex, uint32_t *xdp_flags, int prog_fd)
return EXIT_SUCCESS;
}
void SetConfigDefaultsX(struct config_map *cfg)
{
cfg->updateTime = 0;
cfg->interface = "eth0";
for (uint16_t i = 0; i < MAX_FILTERS; i++)
{
cfg->filters[i].enabled = 0;
cfg->filters[i].action = 0;
cfg->filters[i].srcIP = 0;
cfg->filters[i].dstIP = 0;
cfg->filters[i].min_id = 0;
cfg->filters[i].max_id = 4294967295;
cfg->filters[i].min_len = 0;
cfg->filters[i].max_len = 65535;
cfg->filters[i].min_ttl = 0;
cfg->filters[i].max_ttl = 255;
cfg->filters[i].tos = 0;
cfg->filters[i].tcpopts.enabled = 0;
cfg->filters[i].udpopts.enabled = 0;
cfg->filters[i].icmpopts.enabled = 0;
for (uint16_t j = 0; i < MAX_PCKT_LENGTH; i++)
{
cfg->filters[i].payloadMatch[j] = 0;
}
cfg->filters[i].payloadLen = 0;
}
}
int main(int argc, char *argv[])
{
// Parse the command line.
@@ -311,11 +280,12 @@ int main(int argc, char *argv[])
// Initialize config.
struct config_map *conf = malloc(sizeof(struct config_map));
SetConfigDefaults(conf);
// Create last updated variable.
time_t lastUpdated = time(NULL);
time_t statsLastUpdated = time(NULL);
// Update config.
update_config(conf, configFile);
@@ -333,6 +303,7 @@ int main(int argc, char *argv[])
fprintf(stdout, "Filter #%" PRIu16 ":\n", (i + 1));
// Main.
fprintf(stdout, "ID => %d\n", conf->filters[i].id);
fprintf(stdout, "Enabled => %" PRIu8 "\n", conf->filters[i].enabled);
fprintf(stdout, "Action => %" PRIu8 " (0 = Block, 1 = Allow).\n", conf->filters[i].action);
@@ -350,8 +321,6 @@ int main(int argc, char *argv[])
fprintf(stdout, "Min Length => %" PRIu16 "\n", conf->filters[i].min_len);
fprintf(stdout, "Max TTL => %" PRIu8 "\n", conf->filters[i].max_ttl);
fprintf(stdout, "Min TTL => %" PRIu8 "\n", conf->filters[i].min_ttl);
fprintf(stdout, "Max ID => %" PRIu32 "\n", conf->filters[i].max_id);
fprintf(stdout, "Min ID => %" PRIu32 "\n", conf->filters[i].min_id);
fprintf(stdout, "TOS => %" PRIu8 "\n\n", conf->filters[i].tos);
// TCP Options.
@@ -417,7 +386,7 @@ int main(int argc, char *argv[])
// Check for valid maps.
if (filter_map_fd < 0)
{
fprintf(stderr, "Error finding 'filters_map' BPF map\n");
fprintf(stderr, "Error finding 'filters_map' BPF map.\n");
return EXIT_FAILURE;
}
@@ -429,6 +398,16 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
if (stats_map_fd < 0)
{
fprintf(stderr, "Error finding 'stats_map' BPF map.\n");
return EXIT_FAILURE;
}
// Update BPF maps.
update_BPF(conf);
// Signal.
signal(SIGINT, signalHndl);
@@ -450,6 +429,23 @@ int main(int argc, char *argv[])
lastUpdated = time(NULL);
}
// Update stats.
if ((curTime - statsLastUpdated) > 5)
{
uint16_t key = 0;
struct xdpfw_stats *stats;
bpf_map_lookup_elem(stats_map_fd, &key, stats);
if (stats != NULL)
{
fprintf(stdout, "\rPackets allowed: %" PRIu64 "\n", stats->allowed);
fprintf(stdout, "\rPackets blocked: %" PRIu64 "\n", stats->blocked);
fflush(stdout);
}
}
sleep(1);
}