From 66364a1f6b3f88d70bb4611efc3d3c9b9c304639 Mon Sep 17 00:00:00 2001 From: Christian Deacon Date: Tue, 5 May 2020 16:35:24 +0000 Subject: [PATCH] Fixed segfault crashes and improved code. --- src/config.c | 218 ++++++++++++++++++++++---------------------- src/include/xdpfw.h | 1 - src/xdpfw_loader.c | 152 +++++++++++++++++++----------- 3 files changed, 209 insertions(+), 162 deletions(-) diff --git a/src/config.c b/src/config.c index 8c82f5b..d951599 100644 --- a/src/config.c +++ b/src/config.c @@ -28,13 +28,12 @@ void SetConfigDefaults(struct config_map *cfg) cfg->filters[i].min_ttl = 0; cfg->filters[i].max_ttl = 255; cfg->filters[i].tos = 0; - cfg->filters[i].protocol = 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++) + for (uint16_t j = 0; j < MAX_PCKT_LENGTH - 1; j++) { cfg->filters[i].payloadMatch[j] = 0; } @@ -105,7 +104,7 @@ int ReadConfig(struct config_map *cfg) // Get auto update time. int updateTime; - if (!config_lookup_bool(&conf, "updatetime", &updateTime)) + if (!config_lookup_int(&conf, "updatetime", &updateTime)) { fprintf(stderr, "Error from LibConfig when reading 'updatetime' setting - %s\n\n", config_error_text(&conf)); @@ -139,7 +138,7 @@ int ReadConfig(struct config_map *cfg) // Enabled. int enabled; - if (config_setting_lookup_bool(filter, "enabled", &enabled) != 0) + if (config_setting_lookup_bool(filter, "enabled", &enabled) == CONFIG_FALSE) { // Print error and stop from existing this rule any further. fprintf(stderr, "Error from LibConfig when reading 'enabled' setting from filters array #%d. Error - %s\n\n", filters, config_error_text(&conf)); @@ -152,7 +151,7 @@ int ReadConfig(struct config_map *cfg) // Action (required). int action; - if (config_setting_lookup_int(filter, "action", &action) != 0) + if (config_setting_lookup_int(filter, "action", &action) == CONFIG_FALSE) { fprintf(stderr, "Error from LibConfig when reading 'action' setting from filters array #%d. Error - %s\n\n", filters, config_error_text(&conf)); @@ -179,26 +178,12 @@ int ReadConfig(struct config_map *cfg) cfg->filters[i].dstIP = inet_addr(dIP); } - // Protocol (required). - int protocol; - - if (!config_setting_lookup_int(filter, "protocol", &protocol)) - { - fprintf(stderr, "Error from LibConfig when reading 'protocol' setting from filters array #%d. Error - %s\n\n", filters, config_error_text(&conf)); - - cfg->filters[i].enabled = 0; - - continue; - } - - cfg->filters[i].protocol = protocol; - // Minimum TTL (not required). int min_ttl; if (config_setting_lookup_int(filter, "min_ttl", &min_ttl)) { - cfg->filters[i].min_ttl = min_ttl; + cfg->filters[i].min_ttl = (uint8_t)min_ttl; } // Maximum TTL (not required). @@ -206,7 +191,7 @@ int ReadConfig(struct config_map *cfg) if (config_setting_lookup_int(filter, "max_ttl", &max_ttl)) { - cfg->filters[i].max_ttl = max_ttl; + cfg->filters[i].max_ttl = (uint8_t)max_ttl; } // Minimum length (not required). @@ -230,7 +215,7 @@ int ReadConfig(struct config_map *cfg) if (config_setting_lookup_int(filter, "tos", &tos)) { - cfg->filters[i].tos = tos; + cfg->filters[i].tos = (uint8_t)tos; } // Payload match. @@ -262,76 +247,81 @@ int ReadConfig(struct config_map *cfg) // Check TCP options. if (tcpopts != NULL) { - // Enabled. - int enabled; - - if (config_setting_lookup_bool(tcpopts, "enabled", &enabled)) + for (uint16_t j = 0; j < config_setting_length(tcpopts); j++) { - cfg->filters[i].tcpopts.enabled = enabled; - } + config_setting_t* tcp = config_setting_get_elem(tcpopts, j); - // Source port. - long long sport; + // Enabled. + int enabled; - if (config_setting_lookup_int64(tcpopts, "sport", &sport)) - { - cfg->filters[i].tcpopts.sport = (uint16_t)sport; - } + if (config_setting_lookup_bool(tcp, "enabled", &enabled)) + { + cfg->filters[i].tcpopts.enabled = enabled; + } - // Destination port. - long long dport; + // Source port. + long long sport; - if (config_setting_lookup_int64(tcpopts, "dport", &dport)) - { - cfg->filters[i].tcpopts.dport = (uint16_t)dport; - } + if (config_setting_lookup_int64(tcp, "sport", &sport)) + { + cfg->filters[i].tcpopts.sport = (uint16_t)sport; + } - // URG flag. - int urg; + // Destination port. + long long dport; - if (config_setting_lookup_bool(tcpopts, "urg", &urg)) - { - cfg->filters[i].tcpopts.urg = urg; - } + if (config_setting_lookup_int64(tcp, "dport", &dport)) + { + cfg->filters[i].tcpopts.dport = (uint16_t)dport; + } - // ACK flag. - int ack; + // URG flag. + int urg; - if (config_setting_lookup_bool(tcpopts, "ack", &ack)) - { - cfg->filters[i].tcpopts.ack = ack; - } + if (config_setting_lookup_bool(tcp, "urg", &urg)) + { + cfg->filters[i].tcpopts.urg = urg; + } - // RST flag. - int rst; + // ACK flag. + int ack; - if (config_setting_lookup_bool(tcpopts, "rst", &rst)) - { - cfg->filters[i].tcpopts.rst = rst; - } + if (config_setting_lookup_bool(tcp, "ack", &ack)) + { + cfg->filters[i].tcpopts.ack = ack; + } - // PSH flag. - int psh; + // RST flag. + int rst; - if (config_setting_lookup_bool(tcpopts, "psh", &psh)) - { - cfg->filters[i].tcpopts.psh = psh; - } + if (config_setting_lookup_bool(tcp, "rst", &rst)) + { + cfg->filters[i].tcpopts.rst = rst; + } - // SYN flag. - int syn; + // PSH flag. + int psh; - if (config_setting_lookup_bool(tcpopts, "syn", &syn)) - { - cfg->filters[i].tcpopts.syn = syn; - } + if (config_setting_lookup_bool(tcp, "psh", &psh)) + { + cfg->filters[i].tcpopts.psh = psh; + } - // FIN flag. - int fin; + // SYN flag. + int syn; - if (config_setting_lookup_bool(tcpopts, "fin", &fin)) - { - cfg->filters[i].tcpopts.fin = fin; + if (config_setting_lookup_bool(tcp, "syn", &syn)) + { + cfg->filters[i].tcpopts.syn = syn; + } + + // FIN flag. + int fin; + + if (config_setting_lookup_bool(tcp, "fin", &fin)) + { + cfg->filters[i].tcpopts.fin = fin; + } } } @@ -341,28 +331,33 @@ int ReadConfig(struct config_map *cfg) // Check UDP options. if (udpopts != NULL) { - // Enabled. - int enabled; - - if (config_setting_lookup_bool(udpopts, "enabled", &enabled)) + for (uint16_t j = 0; j < config_setting_length(udpopts); j++) { - cfg->filters[i].udpopts.enabled = enabled; - } + config_setting_t* udp = config_setting_get_elem(udpopts, j); - // Source port. - long long sport; + // Enabled. + int enabled; - if (config_setting_lookup_int64(udpopts, "sport", &sport)) - { - cfg->filters[i].udpopts.sport = (uint16_t)sport; - } + if (config_setting_lookup_bool(udp, "enabled", &enabled)) + { + cfg->filters[i].udpopts.enabled = enabled; + } - // Destination port. - long long dport; + // Source port. + long long sport; - if (config_setting_lookup_int64(udpopts, "dport", &dport)) - { - cfg->filters[i].udpopts.dport = (uint16_t)dport; + if (config_setting_lookup_int64(udp, "sport", &sport)) + { + cfg->filters[i].udpopts.sport = (uint16_t)sport; + } + + // Destination port. + long long dport; + + if (config_setting_lookup_int64(udp, "dport", &dport)) + { + cfg->filters[i].udpopts.dport = (uint16_t)dport; + } } } @@ -372,28 +367,33 @@ int ReadConfig(struct config_map *cfg) // Check UDP options. if (icmpopts != NULL) { - // Enabled. - int enabled; - - if (config_setting_lookup_bool(icmpopts, "enabled", &enabled)) + for (uint16_t j = 0; j < config_setting_length(icmpopts); j++) { - cfg->filters[i].icmpopts.enabled = enabled; - } + config_setting_t* icmp = config_setting_get_elem(icmpopts, j); + + // Enabled. + int enabled; - // ICMP code. - int code; + if (config_setting_lookup_bool(icmp, "enabled", &enabled)) + { + cfg->filters[i].icmpopts.enabled = enabled; + } - if (config_setting_lookup_int(icmpopts, "code", &code)) - { - cfg->filters[i].icmpopts.code = code; - } + // ICMP code. + int code; - // ICMP type. - int type; + if (config_setting_lookup_int(icmp, "code", &code)) + { + cfg->filters[i].icmpopts.code = (uint8_t)code; + } - if (config_setting_lookup_int(icmpopts, "type", &type)) - { - cfg->filters[i].icmpopts.type = type; + // ICMP type. + int type; + + if (config_setting_lookup_int(icmp, "type", &type)) + { + cfg->filters[i].icmpopts.type = (uint8_t)type; + } } } diff --git a/src/include/xdpfw.h b/src/include/xdpfw.h index 74c1dcd..fde634a 100644 --- a/src/include/xdpfw.h +++ b/src/include/xdpfw.h @@ -46,7 +46,6 @@ struct filter uint32_t srcIP; uint32_t dstIP; - uint8_t protocol; uint8_t min_ttl; uint8_t max_ttl; diff --git a/src/xdpfw_loader.c b/src/xdpfw_loader.c index b381e17..129bc88 100644 --- a/src/xdpfw_loader.c +++ b/src/xdpfw_loader.c @@ -3,10 +3,10 @@ #include #include #include -#include #include #include #include +#include #include #include @@ -45,7 +45,7 @@ void parse_command_line(int argc, char *argv[]) { int c; - while ((c = getopt_long(argc, argv, "c:hl", opts, 0)) != -1) + while ((c = getopt_long(argc, argv, "c:lh", opts, NULL)) != -1) { switch (c) { @@ -54,10 +54,23 @@ void parse_command_line(int argc, char *argv[]) break; + case 'l': + list = 1; + + break; + + case 'h': + help = 1; + + break; + case '?': fprintf(stderr, "Missing argument option...\n"); break; + + default: + break; } } } @@ -241,6 +254,38 @@ 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. @@ -254,7 +299,7 @@ int main(int argc, char *argv[]) "--list -l => Print config details including filters (this will exit program after done).\n" \ "--help -h => Print help menu.\n"); - exit(EXIT_SUCCESS); + return EXIT_SUCCESS; } // Check for --config argument. @@ -265,85 +310,85 @@ int main(int argc, char *argv[]) } // Initialize config. - struct config_map conf; + struct config_map *conf = malloc(sizeof(struct config_map)); - SetConfigDefaults(&conf); + SetConfigDefaults(conf); // Create last updated variable. time_t lastUpdated = time(NULL); // Update config. - update_config(&conf, configFile); + update_config(conf, configFile); // Check for list option. if (list) { fprintf(stdout, "Details:\n"); - fprintf(stdout, "Interface Name => %s\n", conf.interface); - fprintf(stdout, "Update Time => %" PRIu16 "\n", conf.updateTime); - fprintf(stdout, "Filters Count => %" PRIu16 "\n\n", conf.filterCount); + fprintf(stdout, "Interface Name => %s\n", conf->interface); + fprintf(stdout, "Update Time => %" PRIu16 "\n", conf->updateTime); + fprintf(stdout, "Filters Count => %" PRIu16 "\n\n", conf->filterCount); - for (uint16_t i = 0; i < conf.filterCount; i++) + for (uint16_t i = 0; i < conf->filterCount; i++) { - fprintf(stdout, "Filter #" PRIu16 ":\n"); + fprintf(stdout, "Filter #%" PRIu16 ":\n", (i + 1)); // Main. - fprintf(stdout, "Enabled => %" PRIu8 "\n", conf.filters[i].enabled); - fprintf(stdout, "Action => %" PRIu8 " (0 = Block, 1 = Allow).\n", conf.filters[i].action); + fprintf(stdout, "Enabled => %" PRIu8 "\n", conf->filters[i].enabled); + fprintf(stdout, "Action => %" PRIu8 " (0 = Block, 1 = Allow).\n", conf->filters[i].action); // IP addresses. struct sockaddr_in sin; - sin.sin_addr.s_addr = conf.filters[i].srcIP; + sin.sin_addr.s_addr = conf->filters[i].srcIP; fprintf(stdout, "Source IP => %s\n", inet_ntoa(sin.sin_addr)); struct sockaddr_in din; - din.sin_addr.s_addr = conf.filters[i].dstIP; + din.sin_addr.s_addr = conf->filters[i].dstIP; fprintf(stdout, "Destination IP => %s\n", inet_ntoa(din.sin_addr)); // Other IP header information. - fprintf(stdout, "Max Length => %" PRIu16 "\n", conf.filters[i].max_len); - 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", conf.filters[i].tos); + fprintf(stdout, "Max Length => %" PRIu16 "\n", conf->filters[i].max_len); + 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. - fprintf(stdout, "TCP Enabled => %" PRIu8 "\n", conf.filters[i].tcpopts.enabled); - fprintf(stdout, "TCP Source Port => %" PRIu16 "\n", conf.filters[i].tcpopts.sport); - fprintf(stdout, "TCP Destination Port => %" PRIu16 "\n", conf.filters[i].tcpopts.dport); - fprintf(stdout, "TCP URG Flag => %" PRIu8 "\n", conf.filters[i].tcpopts.urg); - fprintf(stdout, "TCP ACK Flag => %" PRIu8 "\n", conf.filters[i].tcpopts.ack); - fprintf(stdout, "TCP RST Flag => %" PRIu8 "\n", conf.filters[i].tcpopts.rst); - fprintf(stdout, "TCP PSH Flag => %" PRIu8 "\n", conf.filters[i].tcpopts.psh); - fprintf(stdout, "TCP SYN Flag => %" PRIu8 "\n", conf.filters[i].tcpopts.syn); - fprintf(stdout, "TCP FIN Flag => %" PRIu8 "\n", conf.filters[i].tcpopts.fin); + fprintf(stdout, "TCP Enabled => %" PRIu8 "\n", conf->filters[i].tcpopts.enabled); + fprintf(stdout, "TCP Source Port => %" PRIu16 "\n", conf->filters[i].tcpopts.sport); + fprintf(stdout, "TCP Destination Port => %" PRIu16 "\n", conf->filters[i].tcpopts.dport); + fprintf(stdout, "TCP URG Flag => %" PRIu8 "\n", conf->filters[i].tcpopts.urg); + fprintf(stdout, "TCP ACK Flag => %" PRIu8 "\n", conf->filters[i].tcpopts.ack); + fprintf(stdout, "TCP RST Flag => %" PRIu8 "\n", conf->filters[i].tcpopts.rst); + fprintf(stdout, "TCP PSH Flag => %" PRIu8 "\n", conf->filters[i].tcpopts.psh); + fprintf(stdout, "TCP SYN Flag => %" PRIu8 "\n", conf->filters[i].tcpopts.syn); + fprintf(stdout, "TCP FIN Flag => %" PRIu8 "\n\n", conf->filters[i].tcpopts.fin); // UDP Options. - fprintf(stdout, "UDP Enabled => %" PRIu8 "\n", conf.filters[i].udpopts.enabled); - fprintf(stdout, "UDP Source Port => %" PRIu16 "\n", conf.filters[i].udpopts.sport); - fprintf(stdout, "UDP Destination Port => %" PRIu16 "\n", conf.filters[i].udpopts.dport); + fprintf(stdout, "UDP Enabled => %" PRIu8 "\n", conf->filters[i].udpopts.enabled); + fprintf(stdout, "UDP Source Port => %" PRIu16 "\n", conf->filters[i].udpopts.sport); + fprintf(stdout, "UDP Destination Port => %" PRIu16 "\n\n", conf->filters[i].udpopts.dport); // ICMP Options. - fprintf(stdout, "ICMP Enabled => %" PRIu8 "\n", conf.filters[i].icmpopts.enabled); - fprintf(stdout, "ICMP Code => %" PRIu8 "\n", conf.filters[i].icmpopts.code); - fprintf(stdout, "ICMP Type => %" PRIu8 "\n", conf.filters[i].icmpopts.type); + fprintf(stdout, "ICMP Enabled => %" PRIu8 "\n", conf->filters[i].icmpopts.enabled); + fprintf(stdout, "ICMP Code => %" PRIu8 "\n", conf->filters[i].icmpopts.code); + fprintf(stdout, "ICMP Type => %" PRIu8 "\n", conf->filters[i].icmpopts.type); - fprintf(stdout, "\n"); + fprintf(stdout, "\n\n"); } - exit(EXIT_SUCCESS); + return EXIT_SUCCESS; } // Get device. int dev; - if ((dev = if_nametoindex(conf.interface)) < 0) + if ((dev = if_nametoindex(conf->interface)) < 0) { - fprintf(stderr, "Error finding device %s.\n", conf.interface); + fprintf(stderr, "Error finding device %s.\n", conf->interface); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } // XDP variables. @@ -360,13 +405,13 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Error loading eBPF object file. File name => %s.\n", filename); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } // Attach XDP program to device. if (xdp_attach(dev, &xdpflags, prog_fd) != 0) { - exit(EXIT_FAILURE); + return EXIT_FAILURE; } // Check for valid maps. @@ -374,14 +419,14 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Error finding 'filters_map' BPF map\n"); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } if (count_map_fd < 0) { fprintf(stderr, "Error finding 'count_map' BPF map.\n"); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } // Signal. @@ -393,13 +438,13 @@ int main(int argc, char *argv[]) time_t curTime = time(NULL); // Check for auto-update. - if (conf.updateTime > 0 && (curTime - lastUpdated) > conf.updateTime) + if (conf->updateTime > 0 && (curTime - lastUpdated) > conf->updateTime) { // Update config. - update_config(&conf, configFile); + update_config(conf, configFile); // Update BPF maps. - update_BPF(&conf); + update_BPF(conf); // Update last updated variable. lastUpdated = time(NULL); @@ -411,11 +456,14 @@ int main(int argc, char *argv[]) // Detach XDP program. if (xdp_detach(dev, xdpflags) != 0) { - fprintf(stderr, "Error removing XDP program from device %s\n", conf.interface); + fprintf(stderr, "Error removing XDP program from device %s\n", conf->interface); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } + // Free config. + free(conf); + // Exit program successfully. - exit(EXIT_SUCCESS); + return EXIT_SUCCESS; } \ No newline at end of file