From f88a52f792b3f4597d5703c9b707a8317419dab9 Mon Sep 17 00:00:00 2001 From: Christian Deacon Date: Tue, 5 May 2020 23:58:34 +0000 Subject: [PATCH] Improved config and added additional functionality. --- src/config.c | 49 +++++++++++++++++++++++++-- src/include/xdpfw.h | 41 ++++++++++++++++++++--- src/xdpfw_loader.c | 82 +++++++++++++++++++++------------------------ 3 files changed, 122 insertions(+), 50 deletions(-) diff --git a/src/config.c b/src/config.c index d951599..c014e9b 100644 --- a/src/config.c +++ b/src/config.c @@ -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++; } diff --git a/src/include/xdpfw.h b/src/include/xdpfw.h index fde634a..0d52ebc 100644 --- a/src/include/xdpfw.h +++ b/src/include/xdpfw.h @@ -4,21 +4,35 @@ #include #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 \ No newline at end of file diff --git a/src/xdpfw_loader.c b/src/xdpfw_loader.c index 129bc88..82d2997 100644 --- a/src/xdpfw_loader.c +++ b/src/xdpfw_loader.c @@ -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); }