Start preparing loader for xdpfw-add (rule_add) and xdpfw-del (rule_del) programs.
This commit is contained in:
@@ -21,6 +21,34 @@
|
||||
int cont = 1;
|
||||
int doing_stats = 0;
|
||||
|
||||
/**
|
||||
* Unpins filter-specific BPF maps from file system.
|
||||
*
|
||||
* @param cfg A pointer to the config structure.
|
||||
* @param obj A pointer to the BPF object.
|
||||
* @param ignore_errors Whether to ignore errors.
|
||||
*/
|
||||
static void UnpinFilterMaps(config__t* cfg, struct bpf_object* obj, int ignore_errors)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = UnpinBpfMap(obj, XDP_MAP_PIN_DIR, "map_filters")) != 0)
|
||||
{
|
||||
if (!ignore_errors)
|
||||
{
|
||||
LogMsg(cfg, 1, 0, "[WARNING] Failed to un-pin BPF map 'map_filters' from file system (%d).", ret);
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = UnpinBpfMap(obj, XDP_MAP_PIN_DIR, "map_filter_log")) != 0)
|
||||
{
|
||||
if (!ignore_errors)
|
||||
{
|
||||
LogMsg(cfg, 1, 0, "[WARNING] Failed to un-pin BPF map 'map_filter_log' from file system (%d).", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
@@ -29,6 +57,7 @@ int main(int argc, char *argv[])
|
||||
cmdline_t cmd = {0};
|
||||
cmd.cfgfile = CONFIG_DEFAULT_PATH;
|
||||
cmd.verbose = -1;
|
||||
cmd.pin_maps = -1;
|
||||
cmd.update_time = -1;
|
||||
cmd.no_stats = -1;
|
||||
cmd.stats_per_second = -1;
|
||||
@@ -54,6 +83,7 @@ int main(int argc, char *argv[])
|
||||
cfg_overrides.verbose = cmd.verbose;
|
||||
cfg_overrides.log_file = cmd.log_file;
|
||||
cfg_overrides.interface = cmd.interface;
|
||||
cfg_overrides.pin_maps = cmd.pin_maps;
|
||||
cfg_overrides.update_time = cmd.update_time;
|
||||
cfg_overrides.no_stats = cmd.no_stats;
|
||||
cfg_overrides.stats_per_second = cmd.stats_per_second;
|
||||
@@ -140,7 +170,7 @@ int main(int argc, char *argv[])
|
||||
// Attach XDP program.
|
||||
char *mode_used = NULL;
|
||||
|
||||
if ((ret = AttachXdp(prog, &mode_used, ifidx, 0, &cmd)) != 0)
|
||||
if ((ret = AttachXdp(prog, &mode_used, ifidx, 0, cmd.skb, cmd.offload)) != 0)
|
||||
{
|
||||
LogMsg(&cfg, 0, 1, "[ERROR] Failed to attach XDP program to interface '%s' using available modes (%d).\n", cfg.interface, ret);
|
||||
|
||||
@@ -194,6 +224,36 @@ int main(int argc, char *argv[])
|
||||
|
||||
LogMsg(&cfg, 3, 0, "map_stats FD => %d.", map_stats);
|
||||
|
||||
// Pin BPF maps to file system if we need to.
|
||||
if (cfg.pin_maps)
|
||||
{
|
||||
LogMsg(&cfg, 2, 0, "Pinning BPF maps...");
|
||||
|
||||
struct bpf_object* obj = GetBpfObj(prog);
|
||||
|
||||
// There are times where the BPF maps from the last run weren't cleaned up properly.
|
||||
// So it's best to attempt to unpin the maps before pinning while ignoring errors.
|
||||
UnpinFilterMaps(&cfg, obj, 1);
|
||||
|
||||
if ((ret = PinBpfMap(obj, XDP_MAP_PIN_DIR, "map_filters")) != 0)
|
||||
{
|
||||
LogMsg(&cfg, 1, 0, "[WARNING] Failed to pin 'map_filters' to file system (%d)...", ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMsg(&cfg, 3, 0, "BPF map 'map_filters' pinned to '%s/map_filters'.", XDP_MAP_PIN_DIR);
|
||||
}
|
||||
|
||||
if ((ret = PinBpfMap(obj, XDP_MAP_PIN_DIR, "map_filter_log")) != 0)
|
||||
{
|
||||
LogMsg(&cfg, 1, 0, "[WARNING] Failed to pin 'map_filter_log' to file system (%d)...", ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMsg(&cfg, 3, 0, "BPF map 'map_filter_log' pinned to '%s/map_filter_log'.", XDP_MAP_PIN_DIR);
|
||||
}
|
||||
}
|
||||
|
||||
LogMsg(&cfg, 2, 0, "Updating filters...");
|
||||
|
||||
// Update BPF maps.
|
||||
@@ -281,6 +341,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
LogMsg(&cfg, 2, 0, "Cleaning up...");
|
||||
|
||||
#ifdef ENABLE_FILTER_LOGGING
|
||||
if (rb)
|
||||
{
|
||||
@@ -289,14 +351,27 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
// Detach XDP program.
|
||||
if (AttachXdp(prog, &mode_used, ifidx, 1, &cmd))
|
||||
if (AttachXdp(prog, &mode_used, ifidx, 1, cmd.skb, cmd.offload))
|
||||
{
|
||||
LogMsg(&cfg, 0, 1, "[ERROR] Failed to detach XDP program from interface '%s'.\n", cfg.interface);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
LogMsg(&cfg, 1, 0, "Cleaned up and exiting...\n");
|
||||
// Unpin maps from file system.
|
||||
if (cfg.pin_maps)
|
||||
{
|
||||
LogMsg(&cfg, 2, 0, "Un-pinning BPF maps from file system...");
|
||||
|
||||
struct bpf_object* obj = GetBpfObj(prog);
|
||||
|
||||
UnpinFilterMaps(&cfg, obj, 0);
|
||||
}
|
||||
|
||||
// Lastly, close the XDP program.
|
||||
xdp_program__close(prog);
|
||||
|
||||
LogMsg(&cfg, 1, 0, "Exiting.\n");
|
||||
|
||||
// Exit program successfully.
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
@@ -16,6 +16,7 @@ struct cmdline
|
||||
int verbose;
|
||||
char* log_file;
|
||||
char* interface;
|
||||
int pin_maps;
|
||||
int update_time;
|
||||
int no_stats;
|
||||
int stats_per_second;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include <loader/utils/config.h>
|
||||
|
||||
static FILE *file;
|
||||
|
||||
/**
|
||||
* Loads the config from the file system.
|
||||
*
|
||||
@@ -13,107 +11,56 @@ static FILE *file;
|
||||
*/
|
||||
int LoadConfig(config__t *cfg, char *cfg_file, config_overrides_t* overrides)
|
||||
{
|
||||
int ret;
|
||||
|
||||
FILE *file = NULL;
|
||||
|
||||
// Open config file.
|
||||
if (OpenCfg(cfg_file) != 0)
|
||||
if ((ret = OpenCfg(&file, cfg_file)) != 0 || file == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error opening config file.\n");
|
||||
|
||||
return EXIT_FAILURE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
SetCfgDefaults(cfg);
|
||||
|
||||
memset(cfg->filters, 0, sizeof(cfg->filters));
|
||||
|
||||
// Read config and check for errors.
|
||||
if (ReadCfg(cfg, overrides) != 0)
|
||||
char* buffer = NULL;
|
||||
|
||||
// Read config.
|
||||
if ((ret = ReadCfg(file, &buffer)) != 0)
|
||||
{
|
||||
fprintf(stderr, "Error reading config file.\n");
|
||||
|
||||
return EXIT_FAILURE;
|
||||
CloseCfg(file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Parse config.
|
||||
if ((ret = ParseCfg(cfg, buffer, overrides)) != 0)
|
||||
{
|
||||
fprintf(stderr, "Error parsing config file.\n");
|
||||
|
||||
CloseCfg(file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
if ((ret = CloseCfg(file)) != 0)
|
||||
{
|
||||
fprintf(stderr, "Error closing config file.\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the config structure's default values.
|
||||
*
|
||||
* @param cfg A pointer to the config structure.
|
||||
*
|
||||
* @return Void
|
||||
*/
|
||||
void SetCfgDefaults(config__t *cfg)
|
||||
{
|
||||
cfg->verbose = 2;
|
||||
cfg->log_file = strdup("/var/log/xdpfw.log");
|
||||
cfg->update_time = 0;
|
||||
cfg->interface = NULL;
|
||||
cfg->no_stats = 0;
|
||||
cfg->stats_per_second = 0;
|
||||
cfg->stdout_update_time = 1000;
|
||||
|
||||
for (int i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
filter_t* filter = &cfg->filters[i];
|
||||
|
||||
filter->set = 0;
|
||||
filter->enabled = 1;
|
||||
|
||||
filter->log = 0;
|
||||
|
||||
filter->action = 1;
|
||||
filter->src_ip = 0;
|
||||
filter->dst_ip = 0;
|
||||
|
||||
memset(filter->src_ip6, 0, 4);
|
||||
memset(filter->dst_ip6, 0, 4);
|
||||
|
||||
filter->do_min_len = 0;
|
||||
filter->min_len = 0;
|
||||
|
||||
filter->do_max_len = 0;
|
||||
filter->max_len = 65535;
|
||||
|
||||
filter->do_min_ttl = 0;
|
||||
filter->min_ttl = 0;
|
||||
|
||||
filter->do_max_ttl = 0;
|
||||
filter->max_ttl = 255;
|
||||
|
||||
filter->do_tos = 0;
|
||||
filter->tos = 0;
|
||||
|
||||
filter->do_pps = 0;
|
||||
filter->pps = 0;
|
||||
|
||||
filter->do_bps = 0;
|
||||
filter->bps = 0;
|
||||
|
||||
filter->block_time = 1;
|
||||
|
||||
filter->tcpopts.enabled = 0;
|
||||
filter->tcpopts.do_dport = 0;
|
||||
filter->tcpopts.do_dport = 0;
|
||||
filter->tcpopts.do_urg = 0;
|
||||
filter->tcpopts.do_ack = 0;
|
||||
filter->tcpopts.do_rst = 0;
|
||||
filter->tcpopts.do_psh = 0;
|
||||
filter->tcpopts.do_syn = 0;
|
||||
filter->tcpopts.do_fin = 0;
|
||||
filter->tcpopts.do_ece = 0;
|
||||
filter->tcpopts.do_cwr = 0;
|
||||
|
||||
filter->udpopts.enabled = 0;
|
||||
filter->udpopts.do_sport = 0;
|
||||
filter->udpopts.do_dport = 0;
|
||||
|
||||
filter->icmpopts.enabled = 0;
|
||||
filter->icmpopts.do_code = 0;
|
||||
filter->icmpopts.do_type = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the config file.
|
||||
*
|
||||
@@ -121,19 +68,19 @@ void SetCfgDefaults(config__t *cfg)
|
||||
*
|
||||
* @return 0 on success or 1 on error.
|
||||
*/
|
||||
int OpenCfg(const char *file_name)
|
||||
int OpenCfg(FILE** file, const char *file_name)
|
||||
{
|
||||
// Close any existing files.
|
||||
if (file != NULL)
|
||||
if (*file != NULL)
|
||||
{
|
||||
fclose(file);
|
||||
fclose(*file);
|
||||
|
||||
file = NULL;
|
||||
*file = NULL;
|
||||
}
|
||||
|
||||
file = fopen(file_name, "r");
|
||||
*file = fopen(file_name, "r");
|
||||
|
||||
if (file == NULL)
|
||||
if (*file == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -141,22 +88,59 @@ int OpenCfg(const char *file_name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close config file.
|
||||
*
|
||||
* @param file A pointer to the file to close.
|
||||
*
|
||||
* @param return 0 on success or error value of fclose().
|
||||
*/
|
||||
int CloseCfg(FILE* file)
|
||||
{
|
||||
return fclose(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads contents from the config file.
|
||||
*
|
||||
* @param file The file pointer.
|
||||
* @param buffer The buffer to store the data in (manually allocated).
|
||||
*/
|
||||
int ReadCfg(FILE* file, char** buffer)
|
||||
{
|
||||
fseek(file, 0, SEEK_END);
|
||||
long file_size = ftell(file);
|
||||
rewind(file);
|
||||
|
||||
if (file_size <= 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
*buffer = malloc(file_size + 1);
|
||||
|
||||
if (*buffer == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t read = fread(*buffer, 1, file_size, file);
|
||||
(*buffer)[read] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the config file and stores values in config structure.
|
||||
*
|
||||
* @param cfg A pointer to the config structure.
|
||||
* @param data The config data.
|
||||
* @param overrides Overrides to use instead of config values.
|
||||
*
|
||||
* @return 0 on success or 1/-1 on error.
|
||||
*/
|
||||
int ReadCfg(config__t *cfg, config_overrides_t* overrides)
|
||||
int ParseCfg(config__t *cfg, const char* data, config_overrides_t* overrides)
|
||||
{
|
||||
// Not sure why this would be set to NULL after checking for it in OpenConfig(), but just for safety.
|
||||
if (file == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Initialize config.
|
||||
config_t conf;
|
||||
config_setting_t *setting;
|
||||
@@ -164,7 +148,7 @@ int ReadCfg(config__t *cfg, config_overrides_t* overrides)
|
||||
config_init(&conf);
|
||||
|
||||
// Attempt to read the config.
|
||||
if (config_read(&conf, file) == CONFIG_FALSE)
|
||||
if (config_read_string(&conf, data) == CONFIG_FALSE)
|
||||
{
|
||||
LogMsg(cfg, 0, 1, "Error from LibConfig when reading file - %s (Line %d)", config_error_text(&conf), config_error_line(&conf));
|
||||
|
||||
@@ -189,7 +173,7 @@ int ReadCfg(config__t *cfg, config_overrides_t* overrides)
|
||||
|
||||
const char* log_file;
|
||||
|
||||
if (config_lookup_string(&conf, "log_file", &log_file) == CONFIG_TRUE || overrides->log_file != NULL)
|
||||
if (config_lookup_string(&conf, "log_file", &log_file) == CONFIG_TRUE || (overrides && overrides->log_file != NULL))
|
||||
{
|
||||
// We must free previous value to prevent memory leak.
|
||||
if (cfg->log_file != NULL)
|
||||
@@ -226,7 +210,7 @@ int ReadCfg(config__t *cfg, config_overrides_t* overrides)
|
||||
// Get interface.
|
||||
const char *interface;
|
||||
|
||||
if (config_lookup_string(&conf, "interface", &interface) == CONFIG_TRUE || overrides->interface != NULL)
|
||||
if (config_lookup_string(&conf, "interface", &interface) == CONFIG_TRUE || (overrides && overrides->interface != NULL))
|
||||
{
|
||||
// We must free previous value to prevent memory leak.
|
||||
if (cfg->interface != NULL)
|
||||
@@ -245,10 +229,25 @@ int ReadCfg(config__t *cfg, config_overrides_t* overrides)
|
||||
}
|
||||
}
|
||||
|
||||
// Pin BPF maps.
|
||||
int pin_maps;
|
||||
|
||||
if (config_lookup_bool(&conf, "pin_maps", &pin_maps) == CONFIG_TRUE || (overrides && overrides->pin_maps > -1))
|
||||
{
|
||||
if (overrides->pin_maps > -1)
|
||||
{
|
||||
cfg->pin_maps = overrides->pin_maps;
|
||||
}
|
||||
else
|
||||
{
|
||||
cfg->pin_maps = pin_maps;
|
||||
}
|
||||
}
|
||||
|
||||
// Get auto update time.
|
||||
int update_time;
|
||||
|
||||
if (config_lookup_int(&conf, "update_time", &update_time) == CONFIG_TRUE || overrides->update_time > -1)
|
||||
if (config_lookup_int(&conf, "update_time", &update_time) == CONFIG_TRUE || (overrides && overrides->update_time > -1))
|
||||
{
|
||||
if (overrides->update_time > -1)
|
||||
{
|
||||
@@ -263,7 +262,7 @@ int ReadCfg(config__t *cfg, config_overrides_t* overrides)
|
||||
// Get no stats.
|
||||
int no_stats;
|
||||
|
||||
if (config_lookup_bool(&conf, "no_stats", &no_stats) == CONFIG_TRUE || overrides->no_stats > -1)
|
||||
if (config_lookup_bool(&conf, "no_stats", &no_stats) == CONFIG_TRUE || (overrides && overrides->no_stats > -1))
|
||||
{
|
||||
if (overrides->no_stats > -1)
|
||||
{
|
||||
@@ -278,7 +277,7 @@ int ReadCfg(config__t *cfg, config_overrides_t* overrides)
|
||||
// Stats per second.
|
||||
int stats_per_second;
|
||||
|
||||
if (config_lookup_bool(&conf, "stats_per_second", &stats_per_second) == CONFIG_TRUE || overrides->stats_per_second > -1)
|
||||
if (config_lookup_bool(&conf, "stats_per_second", &stats_per_second) == CONFIG_TRUE || (overrides && overrides->stats_per_second > -1))
|
||||
{
|
||||
if (overrides->stats_per_second > -1)
|
||||
{
|
||||
@@ -293,7 +292,7 @@ int ReadCfg(config__t *cfg, config_overrides_t* overrides)
|
||||
// Get stdout update time.
|
||||
int stdout_update_time;
|
||||
|
||||
if (config_lookup_int(&conf, "stdout_update_time", &stdout_update_time) == CONFIG_TRUE || overrides->stdout_update_time > -1)
|
||||
if (config_lookup_int(&conf, "stdout_update_time", &stdout_update_time) == CONFIG_TRUE || (overrides && overrides->stdout_update_time > -1))
|
||||
{
|
||||
if (overrides->stdout_update_time > -1)
|
||||
{
|
||||
@@ -486,18 +485,18 @@ int ReadCfg(config__t *cfg, config_overrides_t* overrides)
|
||||
}
|
||||
|
||||
// Source port.
|
||||
long long tcpsport;
|
||||
int tcpsport;
|
||||
|
||||
if (config_setting_lookup_int64(filter_cfg, "tcp_sport", &tcpsport) == CONFIG_TRUE)
|
||||
if (config_setting_lookup_int(filter_cfg, "tcp_sport", &tcpsport) == CONFIG_TRUE)
|
||||
{
|
||||
filter->tcpopts.sport = (u16)tcpsport;
|
||||
filter->tcpopts.do_sport = 1;
|
||||
}
|
||||
|
||||
// Destination port.
|
||||
long long tcpdport;
|
||||
int tcpdport;
|
||||
|
||||
if (config_setting_lookup_int64(filter_cfg, "tcp_dport", &tcpdport) == CONFIG_TRUE)
|
||||
if (config_setting_lookup_int(filter_cfg, "tcp_dport", &tcpdport) == CONFIG_TRUE)
|
||||
{
|
||||
filter->tcpopts.dport = (u16)tcpdport;
|
||||
filter->tcpopts.do_dport = 1;
|
||||
@@ -521,7 +520,6 @@ int ReadCfg(config__t *cfg, config_overrides_t* overrides)
|
||||
filter->tcpopts.do_ack = 1;
|
||||
}
|
||||
|
||||
|
||||
// RST flag.
|
||||
int tcprst;
|
||||
|
||||
@@ -586,18 +584,18 @@ int ReadCfg(config__t *cfg, config_overrides_t* overrides)
|
||||
}
|
||||
|
||||
// Source port.
|
||||
long long udpsport;
|
||||
int udpsport;
|
||||
|
||||
if (config_setting_lookup_int64(filter_cfg, "udp_sport", &udpsport) == CONFIG_TRUE)
|
||||
if (config_setting_lookup_int(filter_cfg, "udp_sport", &udpsport) == CONFIG_TRUE)
|
||||
{
|
||||
filter->udpopts.sport = (u16)udpsport;
|
||||
filter->udpopts.do_sport = 1;
|
||||
}
|
||||
|
||||
// Destination port.
|
||||
long long udpdport;
|
||||
int udpdport;
|
||||
|
||||
if (config_setting_lookup_int64(filter_cfg, "udp_dport", &udpdport) == CONFIG_TRUE)
|
||||
if (config_setting_lookup_int(filter_cfg, "udp_dport", &udpdport) == CONFIG_TRUE)
|
||||
{
|
||||
filter->udpopts.dport = (u16)udpdport;
|
||||
filter->udpopts.do_dport = 1;
|
||||
@@ -639,6 +637,430 @@ int ReadCfg(config__t *cfg, config_overrides_t* overrides)
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves config to file system.
|
||||
*
|
||||
* @param cfg A pointer to the config.
|
||||
* @param file_path The file path to store the config into.
|
||||
*
|
||||
* @param return 0 on success or 1 on failure.
|
||||
*/
|
||||
int SaveCfg(config__t* cfg, const char* file_path)
|
||||
{
|
||||
config_t conf;
|
||||
config_setting_t *root, *setting;
|
||||
|
||||
FILE* file;
|
||||
|
||||
config_init(&conf);
|
||||
root = config_root_setting(&conf);
|
||||
|
||||
// Add verbose.
|
||||
setting = config_setting_add(root, "verbose", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(setting, cfg->verbose);
|
||||
|
||||
// Add log file.
|
||||
if (cfg->log_file)
|
||||
{
|
||||
setting = config_setting_add(root, "log_file", CONFIG_TYPE_STRING);
|
||||
config_setting_set_string(setting, cfg->log_file);
|
||||
}
|
||||
|
||||
// Add interface.
|
||||
if (cfg->interface)
|
||||
{
|
||||
setting = config_setting_add(root, "interface", CONFIG_TYPE_STRING);
|
||||
config_setting_set_string(setting, cfg->interface);
|
||||
}
|
||||
|
||||
// Add pin maps.
|
||||
setting = config_setting_add(root, "pin_maps", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(setting, cfg->pin_maps);
|
||||
|
||||
// Add update time.
|
||||
setting = config_setting_add(root, "update_time", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(setting, cfg->update_time);
|
||||
|
||||
// Add no stats.
|
||||
setting = config_setting_add(root, "no_stats", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(setting, cfg->no_stats);
|
||||
|
||||
// Add stats per second.
|
||||
setting = config_setting_add(root, "stats_per_second", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(setting, cfg->stats_per_second);
|
||||
|
||||
// Add stdout update time.
|
||||
setting = config_setting_add(root, "stdout_update_time", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(setting, cfg->stdout_update_time);
|
||||
|
||||
// Add filters.
|
||||
config_setting_t* filters = config_setting_add(root, "filters", CONFIG_TYPE_LIST);
|
||||
|
||||
if (filters)
|
||||
{
|
||||
for (int i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
filter_t* filter = &cfg->filters[i];
|
||||
|
||||
if (!filter->set)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
config_setting_t* filter_cfg = config_setting_add(filters, NULL, CONFIG_TYPE_GROUP);
|
||||
|
||||
if (filter_cfg)
|
||||
{
|
||||
// Add enabled setting.
|
||||
config_setting_t* enabled = config_setting_add(filter_cfg, "enabled", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(enabled, filter->enabled);
|
||||
|
||||
// Add log setting.
|
||||
config_setting_t* log = config_setting_add(filter_cfg, "log", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(log, filter->log);
|
||||
|
||||
// Add action setting.
|
||||
config_setting_t* action = config_setting_add(filter_cfg, "action", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(action, filter->action);
|
||||
|
||||
// Add source IPv4.
|
||||
if (filter->src_ip > 0)
|
||||
{
|
||||
char ip_str[INET_ADDRSTRLEN];
|
||||
|
||||
inet_ntop(AF_INET, &filter->src_ip, ip_str, sizeof(ip_str));
|
||||
|
||||
char full_ip[INET_ADDRSTRLEN + 6];
|
||||
snprintf(full_ip, sizeof(full_ip), "%s/%d", ip_str, filter->src_cidr);
|
||||
|
||||
config_setting_t* src_ip = config_setting_add(filter_cfg, "src_ip", CONFIG_TYPE_STRING);
|
||||
config_setting_set_string(src_ip, full_ip);
|
||||
}
|
||||
|
||||
// Add destination IPv4.
|
||||
if (filter->dst_ip > 0)
|
||||
{
|
||||
char ip_str[INET_ADDRSTRLEN];
|
||||
|
||||
inet_ntop(AF_INET, &filter->dst_ip, ip_str, sizeof(ip_str));
|
||||
|
||||
char full_ip[INET_ADDRSTRLEN + 6];
|
||||
snprintf(full_ip, sizeof(full_ip), "%s/%d", ip_str, filter->src_cidr);
|
||||
|
||||
config_setting_t* dst_ip = config_setting_add(filter_cfg, "dst_ip", CONFIG_TYPE_STRING);
|
||||
config_setting_set_string(dst_ip, full_ip);
|
||||
}
|
||||
|
||||
// Add source IPv6.
|
||||
if (memcmp(filter->src_ip6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) != 0)
|
||||
{
|
||||
char ip_str[INET6_ADDRSTRLEN];
|
||||
|
||||
inet_ntop(AF_INET, filter->src_ip6, ip_str, sizeof(ip_str));
|
||||
|
||||
//char full_ip[INET6_ADDRSTRLEN + 6];
|
||||
//snprintf(full_ip, sizeof(full_ip), "%s/%d", ip_str, filter->src_cidr6);
|
||||
|
||||
config_setting_t* src_ip6 = config_setting_add(filter_cfg, "src_ip6", CONFIG_TYPE_STRING);
|
||||
config_setting_set_string(src_ip6, ip_str);
|
||||
}
|
||||
|
||||
// Add source IPv6.
|
||||
if (memcmp(filter->dst_ip6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) != 0)
|
||||
{
|
||||
char ip_str[INET6_ADDRSTRLEN];
|
||||
|
||||
inet_ntop(AF_INET, filter->dst_ip6, ip_str, sizeof(ip_str));
|
||||
|
||||
//char full_ip[INET6_ADDRSTRLEN + 6];
|
||||
//snprintf(full_ip, sizeof(full_ip), "%s/%d", ip_str, filter->src_cidr6);
|
||||
|
||||
config_setting_t* dst_ip6 = config_setting_add(filter_cfg, "dst_ip6", CONFIG_TYPE_STRING);
|
||||
config_setting_set_string(dst_ip6, ip_str);
|
||||
}
|
||||
|
||||
// Add minimum TTL.
|
||||
config_setting_t* min_ttl = config_setting_add(filter_cfg, "min_ttl", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(min_ttl, filter->min_ttl);
|
||||
|
||||
// Add maximum TTL.
|
||||
config_setting_t* max_ttl = config_setting_add(filter_cfg, "max_ttl", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(max_ttl, filter->max_ttl);
|
||||
|
||||
// Add minimum length.
|
||||
config_setting_t* min_len = config_setting_add(filter_cfg, "min_len", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(min_len, filter->min_len);
|
||||
|
||||
// Add maximum length.
|
||||
config_setting_t* max_len = config_setting_add(filter_cfg, "max_len", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(max_len, filter->max_len);
|
||||
|
||||
// Add ToS.
|
||||
config_setting_t* tos = config_setting_add(filter_cfg, "tos", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(tos, filter->tos);
|
||||
|
||||
// Add PPS.
|
||||
config_setting_t* pps = config_setting_add(filter_cfg, "pps", CONFIG_TYPE_INT64);
|
||||
config_setting_set_int64(pps, filter->pps);
|
||||
|
||||
// Add BPS.
|
||||
config_setting_t* bps = config_setting_add(filter_cfg, "bps", CONFIG_TYPE_INT64);
|
||||
config_setting_set_int64(bps, filter->bps);
|
||||
|
||||
// Add block time.
|
||||
config_setting_t* block_time = config_setting_add(filter_cfg, "block_time", CONFIG_TYPE_INT64);
|
||||
config_setting_set_int64(block_time, filter->block_time);
|
||||
|
||||
// Add TCP enabled.
|
||||
config_setting_t* tcp_enabled = config_setting_add(filter_cfg, "tcp_enabled", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(tcp_enabled, filter->tcpopts.enabled);
|
||||
|
||||
// Add TCP source port.
|
||||
config_setting_t* tcp_sport = config_setting_add(filter_cfg, "tcp_sport", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(tcp_sport, filter->tcpopts.sport);
|
||||
|
||||
// Add TCP destination port.
|
||||
config_setting_t* tcp_dport = config_setting_add(filter_cfg, "tcp_dport", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(tcp_dport, filter->tcpopts.dport);
|
||||
|
||||
// Add TCP URG flag.
|
||||
config_setting_t* tcp_urg = config_setting_add(filter_cfg, "tcp_urg", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(tcp_urg, filter->tcpopts.urg);
|
||||
|
||||
// Add TCP ACK flag.
|
||||
config_setting_t* tcp_ack = config_setting_add(filter_cfg, "tcp_ack", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(tcp_ack, filter->tcpopts.ack);
|
||||
|
||||
// Add TCP RST flag.
|
||||
config_setting_t* tcp_rst = config_setting_add(filter_cfg, "tcp_rst", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(tcp_rst, filter->tcpopts.rst);
|
||||
|
||||
// Add TCP PSH flag.
|
||||
config_setting_t* tcp_psh = config_setting_add(filter_cfg, "tcp_psh", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(tcp_psh, filter->tcpopts.psh);
|
||||
|
||||
// Add TCP SYN flag.
|
||||
config_setting_t* tcp_syn = config_setting_add(filter_cfg, "tcp_syn", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(tcp_syn, filter->tcpopts.syn);
|
||||
|
||||
// Add TCP FIN flag.
|
||||
config_setting_t* tcp_fin = config_setting_add(filter_cfg, "tcp_fin", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(tcp_fin, filter->tcpopts.fin);
|
||||
|
||||
// Add TCP ECE flag.
|
||||
config_setting_t* tcp_ece = config_setting_add(filter_cfg, "tcp_ece", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(tcp_ece, filter->tcpopts.ece);
|
||||
|
||||
// Add TCP CWR flag.
|
||||
config_setting_t* tcp_cwr = config_setting_add(filter_cfg, "tcp_cwr", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(tcp_cwr, filter->tcpopts.cwr);
|
||||
|
||||
// Add UDP enabled.
|
||||
config_setting_t* udp_enabled = config_setting_add(filter_cfg, "udp_enabled", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(udp_enabled, filter->udpopts.enabled);
|
||||
|
||||
// Add UDP source port.
|
||||
config_setting_t* udp_sport = config_setting_add(filter_cfg, "udp_sport", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(udp_sport, filter->udpopts.sport);
|
||||
|
||||
// Add UDP destination port.
|
||||
config_setting_t* udp_dport = config_setting_add(filter_cfg, "udp_dport", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(udp_dport, filter->udpopts.dport);
|
||||
|
||||
// Add ICMP enabled.
|
||||
config_setting_t* icmp_enabled = config_setting_add(filter_cfg, "icmp_enabled", CONFIG_TYPE_BOOL);
|
||||
config_setting_set_bool(icmp_enabled, filter->icmpopts.enabled);
|
||||
|
||||
// Add ICMP code.
|
||||
config_setting_t* icmp_code = config_setting_add(filter_cfg, "icmp_code", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(icmp_code, filter->icmpopts.code);
|
||||
|
||||
// Add ICMP type.
|
||||
config_setting_t* icmp_type = config_setting_add(filter_cfg, "icmp_type", CONFIG_TYPE_INT);
|
||||
config_setting_set_int(icmp_type, filter->icmpopts.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write config to file.
|
||||
file = fopen(file_path, "w");
|
||||
|
||||
if (!file)
|
||||
{
|
||||
config_destroy(&conf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
config_write(&conf, file);
|
||||
|
||||
fclose(file);
|
||||
config_destroy(&conf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the config structure's default values.
|
||||
*
|
||||
* @param cfg A pointer to the config structure.
|
||||
*
|
||||
* @return Void
|
||||
*/
|
||||
void SetCfgDefaults(config__t *cfg)
|
||||
{
|
||||
cfg->verbose = 2;
|
||||
cfg->log_file = strdup("/var/log/xdpfw.log");
|
||||
cfg->update_time = 0;
|
||||
cfg->interface = NULL;
|
||||
cfg->pin_maps = 1;
|
||||
cfg->no_stats = 0;
|
||||
cfg->stats_per_second = 0;
|
||||
cfg->stdout_update_time = 1000;
|
||||
|
||||
for (int i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
filter_t* filter = &cfg->filters[i];
|
||||
|
||||
filter->set = 0;
|
||||
filter->enabled = 1;
|
||||
|
||||
filter->log = 0;
|
||||
|
||||
filter->action = 1;
|
||||
filter->src_ip = 0;
|
||||
filter->dst_ip = 0;
|
||||
|
||||
memset(filter->src_ip6, 0, 4);
|
||||
memset(filter->dst_ip6, 0, 4);
|
||||
|
||||
filter->do_min_len = 0;
|
||||
filter->min_len = 0;
|
||||
|
||||
filter->do_max_len = 0;
|
||||
filter->max_len = 65535;
|
||||
|
||||
filter->do_min_ttl = 0;
|
||||
filter->min_ttl = 0;
|
||||
|
||||
filter->do_max_ttl = 0;
|
||||
filter->max_ttl = 255;
|
||||
|
||||
filter->do_tos = 0;
|
||||
filter->tos = 0;
|
||||
|
||||
filter->do_pps = 0;
|
||||
filter->pps = 0;
|
||||
|
||||
filter->do_bps = 0;
|
||||
filter->bps = 0;
|
||||
|
||||
filter->block_time = 1;
|
||||
|
||||
filter->tcpopts.enabled = 0;
|
||||
filter->tcpopts.do_dport = 0;
|
||||
filter->tcpopts.do_dport = 0;
|
||||
filter->tcpopts.do_urg = 0;
|
||||
filter->tcpopts.do_ack = 0;
|
||||
filter->tcpopts.do_rst = 0;
|
||||
filter->tcpopts.do_psh = 0;
|
||||
filter->tcpopts.do_syn = 0;
|
||||
filter->tcpopts.do_fin = 0;
|
||||
filter->tcpopts.do_ece = 0;
|
||||
filter->tcpopts.do_cwr = 0;
|
||||
|
||||
filter->udpopts.enabled = 0;
|
||||
filter->udpopts.do_sport = 0;
|
||||
filter->udpopts.do_dport = 0;
|
||||
|
||||
filter->icmpopts.enabled = 0;
|
||||
filter->icmpopts.do_code = 0;
|
||||
filter->icmpopts.do_type = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a filter rule.
|
||||
*
|
||||
* @param filter A pointer to the filter rule.
|
||||
* @param idx The current index.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void PrintFilter(filter_t* filter, int idx)
|
||||
{
|
||||
printf("\tFilter #%d\n", idx);
|
||||
printf("\t\tEnabled => %d\n", filter->enabled);
|
||||
printf("\t\tAction => %d (0 = Block, 1 = Allow).\n", filter->action);
|
||||
printf("\t\tLog => %d\n\n", filter->log);
|
||||
|
||||
// IP Options.
|
||||
printf("\t\tIP Options\n");
|
||||
|
||||
// IP addresses require additional code for string printing.
|
||||
struct sockaddr_in sin;
|
||||
sin.sin_addr.s_addr = filter->src_ip;
|
||||
printf("\t\t\tSource IPv4 => %s\n", inet_ntoa(sin.sin_addr));
|
||||
printf("\t\t\tSource CIDR => %d\n", filter->src_cidr);
|
||||
|
||||
struct sockaddr_in din;
|
||||
din.sin_addr.s_addr = filter->dst_ip;
|
||||
printf("\t\t\tDestination IPv4 => %s\n", inet_ntoa(din.sin_addr));
|
||||
printf("\t\t\tDestination CIDR => %d\n", filter->dst_cidr);
|
||||
|
||||
struct in6_addr sin6;
|
||||
memcpy(&sin6, &filter->src_ip6, sizeof(sin6));
|
||||
|
||||
char srcipv6[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &sin6, srcipv6, sizeof(srcipv6));
|
||||
|
||||
printf("\t\t\tSource IPv6 => %s\n", srcipv6);
|
||||
|
||||
struct in6_addr din6;
|
||||
memcpy(&din6, &filter->dst_ip6, sizeof(din6));
|
||||
|
||||
char dstipv6[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &din6, dstipv6, sizeof(dstipv6));
|
||||
|
||||
printf("\t\t\tDestination IPv6 => %s\n", dstipv6);
|
||||
|
||||
// Other IP header information.
|
||||
printf("\t\t\tMax Length => %d\n", filter->max_len);
|
||||
printf("\t\t\tMin Length => %d\n", filter->min_len);
|
||||
printf("\t\t\tMax TTL => %d\n", filter->max_ttl);
|
||||
printf("\t\t\tMin TTL => %d\n", filter->min_ttl);
|
||||
printf("\t\t\tTOS => %d\n", filter->tos);
|
||||
printf("\t\t\tPPS => %llu\n", filter->pps);
|
||||
printf("\t\t\tBPS => %llu\n", filter->bps);
|
||||
printf("\t\t\tBlock Time => %llu\n\n", filter->block_time);
|
||||
|
||||
// TCP Options.
|
||||
printf("\t\tTCP Options\n");
|
||||
printf("\t\t\tTCP Enabled => %d\n", filter->tcpopts.enabled);
|
||||
printf("\t\t\tTCP Source Port => %d\n", filter->tcpopts.sport);
|
||||
printf("\t\t\tTCP Destination Port => %d\n", filter->tcpopts.dport);
|
||||
printf("\t\t\tTCP URG Flag => %d\n", filter->tcpopts.urg);
|
||||
printf("\t\t\tTCP ACK Flag => %d\n", filter->tcpopts.ack);
|
||||
printf("\t\t\tTCP RST Flag => %d\n", filter->tcpopts.rst);
|
||||
printf("\t\t\tTCP PSH Flag => %d\n", filter->tcpopts.psh);
|
||||
printf("\t\t\tTCP SYN Flag => %d\n", filter->tcpopts.syn);
|
||||
printf("\t\t\tTCP FIN Flag => %d\n", filter->tcpopts.fin);
|
||||
printf("\t\t\tTCP ECE Flag => %d\n", filter->tcpopts.ece);
|
||||
printf("\t\t\tTCP CWR Flag => %d\n\n", filter->tcpopts.cwr);
|
||||
|
||||
// UDP Options.
|
||||
printf("\t\tUDP Options\n");
|
||||
printf("\t\t\tUDP Enabled => %d\n", filter->udpopts.enabled);
|
||||
printf("\t\t\tUDP Source Port => %d\n", filter->udpopts.sport);
|
||||
printf("\t\t\tUDP Destination Port => %d\n\n", filter->udpopts.dport);
|
||||
|
||||
// ICMP Options.
|
||||
printf("\t\tICMP Options\n");
|
||||
printf("\t\t\tICMP Enabled => %d\n", filter->icmpopts.enabled);
|
||||
printf("\t\t\tICMP Code => %d\n", filter->icmpopts.code);
|
||||
printf("\t\t\tICMP Type => %d\n", filter->icmpopts.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints config settings.
|
||||
*
|
||||
@@ -663,17 +1085,18 @@ void PrintConfig(config__t* cfg)
|
||||
}
|
||||
|
||||
printf("Printing config...\n");
|
||||
printf("\tGeneral Settings\n");
|
||||
printf("General Settings\n");
|
||||
|
||||
printf("\t\tVerbose => %d\n", cfg->verbose);
|
||||
printf("\t\tLog File => %s\n", log_file);
|
||||
printf("\t\tInterface Name => %s\n", interface);
|
||||
printf("\t\tUpdate Time => %d\n", cfg->update_time);
|
||||
printf("\t\tNo Stats => %d\n", cfg->no_stats);
|
||||
printf("\t\tStats Per Second => %d\n", cfg->stats_per_second);
|
||||
printf("\t\tStdout Update Time => %d\n\n", cfg->stdout_update_time);
|
||||
printf("\tVerbose => %d\n", cfg->verbose);
|
||||
printf("\tLog File => %s\n", log_file);
|
||||
printf("\tInterface Name => %s\n", interface);
|
||||
printf("\tPin BPF Maps => %d\n", cfg->pin_maps);
|
||||
printf("\tUpdate Time => %d\n", cfg->update_time);
|
||||
printf("\tNo Stats => %d\n", cfg->no_stats);
|
||||
printf("\tStats Per Second => %d\n", cfg->stats_per_second);
|
||||
printf("\tStdout Update Time => %d\n\n", cfg->stdout_update_time);
|
||||
|
||||
printf("\tFilters\n");
|
||||
printf("Filters\n");
|
||||
|
||||
for (int i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
@@ -684,79 +1107,32 @@ void PrintConfig(config__t* cfg)
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\t\tFilter #%d:\n", (i + 1));
|
||||
|
||||
// Main.
|
||||
printf("\t\t\tEnabled => %d\n", filter->enabled);
|
||||
printf("\t\t\tAction => %d (0 = Block, 1 = Allow).\n", filter->action);
|
||||
printf("\t\t\tLog => %d\n\n", filter->log);
|
||||
|
||||
// IP Options.
|
||||
printf("\t\t\tIP Options\n");
|
||||
|
||||
// IP addresses require additional code for string printing.
|
||||
struct sockaddr_in sin;
|
||||
sin.sin_addr.s_addr = filter->src_ip;
|
||||
printf("\t\t\t\tSource IPv4 => %s\n", inet_ntoa(sin.sin_addr));
|
||||
printf("\t\t\t\tSource CIDR => %d\n", filter->src_cidr);
|
||||
|
||||
struct sockaddr_in din;
|
||||
din.sin_addr.s_addr = filter->dst_ip;
|
||||
printf("\t\t\t\tDestination IPv4 => %s\n", inet_ntoa(din.sin_addr));
|
||||
printf("\t\t\t\tDestination CIDR => %d\n", filter->dst_cidr);
|
||||
|
||||
struct in6_addr sin6;
|
||||
memcpy(&sin6, &filter->src_ip6, sizeof(sin6));
|
||||
|
||||
char srcipv6[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &sin6, srcipv6, sizeof(srcipv6));
|
||||
|
||||
printf("\t\t\t\tSource IPv6 => %s\n", srcipv6);
|
||||
|
||||
struct in6_addr din6;
|
||||
memcpy(&din6, &filter->dst_ip6, sizeof(din6));
|
||||
|
||||
char dstipv6[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &din6, dstipv6, sizeof(dstipv6));
|
||||
|
||||
printf("\t\t\t\tDestination IPv6 => %s\n", dstipv6);
|
||||
|
||||
// Other IP header information.
|
||||
printf("\t\t\t\tMax Length => %d\n", filter->max_len);
|
||||
printf("\t\t\t\tMin Length => %d\n", filter->min_len);
|
||||
printf("\t\t\t\tMax TTL => %d\n", filter->max_ttl);
|
||||
printf("\t\t\t\tMin TTL => %d\n", filter->min_ttl);
|
||||
printf("\t\t\t\tTOS => %d\n", filter->tos);
|
||||
printf("\t\t\t\tPPS => %llu\n", filter->pps);
|
||||
printf("\t\t\t\tBPS => %llu\n", filter->bps);
|
||||
printf("\t\t\t\tBlock Time => %llu\n\n", filter->block_time);
|
||||
|
||||
// TCP Options.
|
||||
printf("\t\t\tTCP Options\n");
|
||||
printf("\t\t\t\tTCP Enabled => %d\n", filter->tcpopts.enabled);
|
||||
printf("\t\t\t\tTCP Source Port => %d\n", filter->tcpopts.sport);
|
||||
printf("\t\t\t\tTCP Destination Port => %d\n", filter->tcpopts.dport);
|
||||
printf("\t\t\t\tTCP URG Flag => %d\n", filter->tcpopts.urg);
|
||||
printf("\t\t\t\tTCP ACK Flag => %d\n", filter->tcpopts.ack);
|
||||
printf("\t\t\t\tTCP RST Flag => %d\n", filter->tcpopts.rst);
|
||||
printf("\t\t\t\tTCP PSH Flag => %d\n", filter->tcpopts.psh);
|
||||
printf("\t\t\t\tTCP SYN Flag => %d\n", filter->tcpopts.syn);
|
||||
printf("\t\t\t\tTCP FIN Flag => %d\n", filter->tcpopts.fin);
|
||||
printf("\t\t\t\tTCP ECE Flag => %d\n", filter->tcpopts.ece);
|
||||
printf("\t\t\t\tTCP CWR Flag => %d\n\n", filter->tcpopts.cwr);
|
||||
|
||||
// UDP Options.
|
||||
printf("\t\t\tUDP Options\n");
|
||||
printf("\t\t\t\tUDP Enabled => %d\n", filter->udpopts.enabled);
|
||||
printf("\t\t\t\tUDP Source Port => %d\n", filter->udpopts.sport);
|
||||
printf("\t\t\t\tUDP Destination Port => %d\n\n", filter->udpopts.dport);
|
||||
|
||||
// ICMP Options.
|
||||
printf("\t\t\tICMP Options\n");
|
||||
printf("\t\t\t\tICMP Enabled => %d\n", filter->icmpopts.enabled);
|
||||
printf("\t\t\t\tICMP Code => %d\n", filter->icmpopts.code);
|
||||
printf("\t\t\t\tICMP Type => %d\n", filter->icmpopts.type);
|
||||
PrintFilter(filter, i + 1);
|
||||
|
||||
printf("\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves next available filter index.
|
||||
*
|
||||
* @param cfg A pointer to the config structure.
|
||||
*
|
||||
* @return The next available index or -1 if there are no available indexes.
|
||||
*/
|
||||
int GetNextAvailableFilterIndex(config__t* cfg)
|
||||
{
|
||||
for (int i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
filter_t* filter = &cfg->filters[i];
|
||||
|
||||
if (filter->set)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -18,6 +18,7 @@ struct config
|
||||
int verbose;
|
||||
char *log_file;
|
||||
char *interface;
|
||||
unsigned int pin_maps : 1;
|
||||
int update_time;
|
||||
unsigned int no_stats : 1;
|
||||
unsigned int stats_per_second : 1;
|
||||
@@ -30,6 +31,7 @@ struct config_overrides
|
||||
int verbose;
|
||||
const char* log_file;
|
||||
const char* interface;
|
||||
int pin_maps;
|
||||
int update_time;
|
||||
int no_stats;
|
||||
int stats_per_second;
|
||||
@@ -37,11 +39,19 @@ struct config_overrides
|
||||
|
||||
} typedef config_overrides_t;
|
||||
|
||||
int LoadConfig(config__t *cfg, char *cfg_file, config_overrides_t* overrides);
|
||||
void SetCfgDefaults(config__t *cfg);
|
||||
|
||||
void PrintFilter(filter_t* filter, int idx);
|
||||
void PrintConfig(config__t* cfg);
|
||||
|
||||
int OpenCfg(const char *filename);
|
||||
int ReadCfg(config__t *cfg, config_overrides_t* overrides);
|
||||
int LoadConfig(config__t *cfg, char *cfg_file, config_overrides_t* overrides);
|
||||
int SaveCfg(config__t* cfg, const char* file_path);
|
||||
|
||||
int OpenCfg(FILE** file, const char *file_name);
|
||||
int CloseCfg(FILE* file);
|
||||
int ReadCfg(FILE* file, char** buffer);
|
||||
int ParseCfg(config__t *cfg, const char* data, config_overrides_t* overrides);
|
||||
|
||||
int GetNextAvailableFilterIndex(config__t* cfg);
|
||||
|
||||
#include <loader/utils/logging.h>
|
||||
@@ -74,7 +74,6 @@ static void LogMsgRaw(int req_lvl, int cur_lvl, int error, const char* log_path,
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
char log_file_msg[len + 22 + 1];
|
||||
|
||||
snprintf(log_file_msg, sizeof(log_file_msg), "[%02d-%02d-%02d %02d:%02d:%02d]%s", tm_val->tm_year % 100, tm_val->tm_mon + 1, tm_val->tm_mday,
|
||||
@@ -143,7 +142,7 @@ int HandleRbEvent(void* ctx, void* data, size_t sz)
|
||||
}
|
||||
|
||||
char src_ip_str[INET6_ADDRSTRLEN];
|
||||
char dst_ip_str[INET_ADDRSTRLEN];
|
||||
char dst_ip_str[INET6_ADDRSTRLEN];
|
||||
|
||||
if (memcmp(e->src_ip6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) != 0)
|
||||
{
|
||||
|
||||
@@ -53,7 +53,8 @@ int CalculateStats(int map_stats, int cpus, int per_second)
|
||||
if (per_second)
|
||||
{
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now); // Get precise time
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
double elapsed_time = (now.tv_sec - last_update_time.tv_sec) +
|
||||
(now.tv_nsec - last_update_time.tv_nsec) / 1e9;
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include <common/all.h>
|
||||
|
||||
#include <loader/utils/cmdline.h>
|
||||
#include <loader/utils/config.h>
|
||||
#include <loader/utils/helpers.h>
|
||||
|
||||
|
||||
@@ -85,6 +85,18 @@ struct xdp_program *LoadBpfObj(const char *file_name)
|
||||
return prog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves BPF object from XDP program.
|
||||
*
|
||||
* @param prog A pointer to the XDP program.
|
||||
*
|
||||
* @return The BPF object.
|
||||
*/
|
||||
struct bpf_object* GetBpfObj(struct xdp_program* prog)
|
||||
{
|
||||
return xdp_program__bpf_obj(prog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to attach or detach (progfd = -1) a BPF/XDP program to an interface.
|
||||
*
|
||||
@@ -92,11 +104,12 @@ struct xdp_program *LoadBpfObj(const char *file_name)
|
||||
* @param mode_used The mode being used.
|
||||
* @param ifidx The index to the interface to attach to.
|
||||
* @param detach If above 0, attempts to detach XDP program.
|
||||
* @param cmd A pointer to a cmdline struct that includes command line arguments (mostly checking for offload/HW mode set).
|
||||
* @param force_skb If set, forces the XDP program to run in SKB mode.
|
||||
* @param force_offload If set, forces the XDP program to run in offload mode.
|
||||
*
|
||||
* @return 0 on success and 1 on error.
|
||||
*/
|
||||
int AttachXdp(struct xdp_program *prog, char** mode, int ifidx, u8 detach, cmdline_t *cmd)
|
||||
int AttachXdp(struct xdp_program *prog, char** mode, int ifidx, int detach, int force_skb, int force_offload)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -104,13 +117,13 @@ int AttachXdp(struct xdp_program *prog, char** mode, int ifidx, u8 detach, cmdli
|
||||
|
||||
*mode = "DRV/native";
|
||||
|
||||
if (cmd->offload)
|
||||
if (force_offload)
|
||||
{
|
||||
*mode = "HW/offload";
|
||||
|
||||
attach_mode = XDP_MODE_HW;
|
||||
}
|
||||
else if (cmd->skb)
|
||||
else if (force_skb)
|
||||
{
|
||||
*mode = "SKB/generic";
|
||||
|
||||
@@ -176,6 +189,58 @@ int AttachXdp(struct xdp_program *prog, char** mode, int ifidx, u8 detach, cmdli
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a filter.
|
||||
*
|
||||
* @param map_filters The filters BPF map FD.
|
||||
* @param idx The filter index to delete.
|
||||
*
|
||||
* @return 0 on success or the error value of bpf_map_delete_elem().
|
||||
*/
|
||||
int DeleteFilter(int map_filters, u32 idx)
|
||||
{
|
||||
return bpf_map_delete_elem(map_filters, &idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all filters.
|
||||
*
|
||||
* @param map_filters The filters BPF map FD.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void DeleteFilters(int map_filters)
|
||||
{
|
||||
for (int i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
DeleteFilter(map_filters, i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a filter rule.
|
||||
*
|
||||
* @param map_filters The filters BPF map FD.
|
||||
* @param filter A pointer to the filter.
|
||||
* @param idx The filter index to insert or update.
|
||||
*
|
||||
* @return 0 on success or error value of bpf_map_update_elem().
|
||||
*/
|
||||
int UpdateFilter(int map_filters, filter_t* filter, int idx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
filter_t filter_cpus[MAX_CPUS];
|
||||
memset(filter_cpus, 0, sizeof(filter_cpus));
|
||||
|
||||
for (int j = 0; j < MAX_CPUS; j++)
|
||||
{
|
||||
filter_cpus[j] = *filter;
|
||||
}
|
||||
|
||||
return bpf_map_update_elem(map_filters, &idx, &filter_cpus, BPF_ANY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the filter's BPF map with current config settings.
|
||||
*
|
||||
@@ -192,13 +257,11 @@ void UpdateFilters(int map_filters, config__t *cfg)
|
||||
// Add a filter to the filter maps.
|
||||
for (int i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
filter_t* filter = &cfg->filters[i];
|
||||
|
||||
// Delete previous rule from BPF 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.
|
||||
u32 key = i;
|
||||
DeleteFilter(map_filters, i);
|
||||
|
||||
bpf_map_delete_elem(map_filters, &key);
|
||||
filter_t* filter = &cfg->filters[i];
|
||||
|
||||
// Only insert set and enabled filters.
|
||||
if (!filter->set || !filter->enabled)
|
||||
@@ -206,21 +269,78 @@ void UpdateFilters(int map_filters, config__t *cfg)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create value array (max CPUs in size) since we're using a per CPU map.
|
||||
filter_t filter_cpus[MAX_CPUS];
|
||||
memset(filter_cpus, 0, sizeof(filter_cpus));
|
||||
|
||||
for (int j = 0; j < MAX_CPUS; j++)
|
||||
// Attempt to update filter.
|
||||
if ((ret = UpdateFilter(map_filters, filter, cur_idx)) != 0)
|
||||
{
|
||||
filter_cpus[j] = *filter;
|
||||
}
|
||||
fprintf(stderr, "[WARNING] Failed to update filter #%d due to BPF update error (%d)...\n", cur_idx, ret);
|
||||
|
||||
// Attempt to update BPF map.
|
||||
if ((ret = bpf_map_update_elem(map_filters, &cur_idx, &filter_cpus, BPF_ANY)) != 0)
|
||||
{
|
||||
fprintf(stderr, "[WARNING] Failed to update filter #%d due to BPF update error (%d)...\n", i, ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
cur_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pins a BPF map to the file system.
|
||||
*
|
||||
* @param obj A pointer to the BPF object.
|
||||
* @param pin_dir The pin directory.
|
||||
* @param map_name The map name.
|
||||
*
|
||||
* @return 0 on success or value of bpf_map__pin() on error.
|
||||
*/
|
||||
int PinBpfMap(struct bpf_object* obj, const char* pin_dir, const char* map_name)
|
||||
{
|
||||
struct bpf_map* map = bpf_object__find_map_by_name(obj, map_name);
|
||||
|
||||
if (!map)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
char full_path[255];
|
||||
snprintf(full_path, sizeof(full_path), "%s/%s", XDP_MAP_PIN_DIR, map_name);
|
||||
|
||||
return bpf_map__pin(map, full_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpins a BPF map from the file system.
|
||||
*
|
||||
* @param obj A pointer to the BPF object.
|
||||
* @param pin_dir The pin directory.
|
||||
* @param map_name The map name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int UnpinBpfMap(struct bpf_object* obj, const char* pin_dir, const char* map_name)
|
||||
{
|
||||
struct bpf_map* map = bpf_object__find_map_by_name(obj, map_name);
|
||||
|
||||
if (!map)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
char full_path[255];
|
||||
snprintf(full_path, sizeof(full_path), "%s/%s", XDP_MAP_PIN_DIR, map_name);
|
||||
|
||||
return bpf_map__unpin(map, full_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a map FD on the file system (pinned).
|
||||
*
|
||||
* @param pin_dir The pin directory.
|
||||
* @param map_name The map name.
|
||||
*
|
||||
* @return The map FD or -1 on error.
|
||||
*/
|
||||
int GetMapPinFd(const char* pin_dir, const char* map_name)
|
||||
{
|
||||
char full_path[255];
|
||||
snprintf(full_path, sizeof(full_path), "%s/%s", pin_dir, map_name);
|
||||
|
||||
return bpf_obj_get(full_path);
|
||||
}
|
||||
@@ -4,14 +4,26 @@
|
||||
|
||||
#include <common/all.h>
|
||||
|
||||
#include <loader/utils/cmdline.h>
|
||||
#include <loader/utils/config.h>
|
||||
#include <loader/utils/helpers.h>
|
||||
|
||||
#define XDP_OBJ_PATH "/etc/xdpfw/xdp_prog.o"
|
||||
#define XDP_MAP_PIN_DIR "/sys/fs/bpf/xdpfw"
|
||||
|
||||
int FindMapFd(struct xdp_program *prog, const char *map_name);
|
||||
void SetLibBPFLogMode(int silent);
|
||||
|
||||
struct xdp_program *LoadBpfObj(const char *file_name);
|
||||
int AttachXdp(struct xdp_program *prog, char** mode, int ifidx, u8 detach, cmdline_t *cmd);
|
||||
struct bpf_object* GetBpfObj(struct xdp_program* prog);
|
||||
|
||||
int AttachXdp(struct xdp_program *prog, char** mode, int ifidx, int detach, int force_skb, int force_offload);
|
||||
|
||||
int DeleteFilter(int map_filters, u32 idx);
|
||||
void DeleteFilters(int map_filters);
|
||||
|
||||
int UpdateFilter(int map_filters, filter_t* filter, int idx);
|
||||
void UpdateFilters(int map_filters, config__t *cfg);
|
||||
|
||||
int PinBpfMap(struct bpf_object* obj, const char* pin_dir, const char* map_name);
|
||||
int UnpinBpfMap(struct bpf_object* obj, const char* pin_dir, const char* map_name);
|
||||
int GetMapPinFd(const char* pin_dir, const char* map_name);
|
||||
Reference in New Issue
Block a user