Implement support for multiple interfaces and improve code.
This commit is contained in:
@@ -39,3 +39,6 @@
|
|||||||
// Enables filter logging through XDP.
|
// Enables filter logging through XDP.
|
||||||
// If performance is a concern, it is best to disable this feature by commenting out the below line with //.
|
// If performance is a concern, it is best to disable this feature by commenting out the below line with //.
|
||||||
#define ENABLE_FILTER_LOGGING
|
#define ENABLE_FILTER_LOGGING
|
||||||
|
|
||||||
|
// Maximum interfaces the firewall can attach to.
|
||||||
|
#define MAX_INTERFACES 6
|
||||||
@@ -111,8 +111,6 @@ int main(int argc, char *argv[])
|
|||||||
// Initialize config.
|
// Initialize config.
|
||||||
config__t cfg = {0};
|
config__t cfg = {0};
|
||||||
|
|
||||||
set_cfg_defaults(&cfg);
|
|
||||||
|
|
||||||
// Create overrides for config and set arguments from CLI.
|
// Create overrides for config and set arguments from CLI.
|
||||||
config_overrides_t cfg_overrides = {0};
|
config_overrides_t cfg_overrides = {0};
|
||||||
cfg_overrides.verbose = cli.verbose;
|
cfg_overrides.verbose = cli.verbose;
|
||||||
@@ -125,7 +123,7 @@ int main(int argc, char *argv[])
|
|||||||
cfg_overrides.stdout_update_time = cli.stdout_update_time;
|
cfg_overrides.stdout_update_time = cli.stdout_update_time;
|
||||||
|
|
||||||
// Load config.
|
// Load config.
|
||||||
if ((ret = load_cfg(&cfg, cli.cfg_file, &cfg_overrides)) != 0)
|
if ((ret = load_cfg(&cfg, cli.cfg_file, 1, &cfg_overrides)) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[ERROR] Failed to load config from file system (%s)(%d).\n", cli.cfg_file, ret);
|
fprintf(stderr, "[ERROR] Failed to load config from file system (%s)(%d).\n", cli.cfg_file, ret);
|
||||||
|
|
||||||
@@ -146,10 +144,10 @@ int main(int argc, char *argv[])
|
|||||||
print_tool_info();
|
print_tool_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check interface.
|
// Check first interface.
|
||||||
if (cfg.interface == NULL)
|
if (cfg.interfaces[0] == NULL)
|
||||||
{
|
{
|
||||||
log_msg(&cfg, 0, 1, "[ERROR] No interface specified in config or CLI override.");
|
log_msg(&cfg, 0, 1, "[ERROR] No interface(s) specified in config or CLI override.");
|
||||||
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@@ -166,18 +164,6 @@ int main(int argc, char *argv[])
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_msg(&cfg, 2, 0, "Retrieving interface index for '%s'...", cfg.interface);
|
|
||||||
|
|
||||||
// Get interface index.
|
|
||||||
int ifidx = if_nametoindex(cfg.interface);
|
|
||||||
|
|
||||||
if (ifidx < 0)
|
|
||||||
{
|
|
||||||
log_msg(&cfg, 0, 1, "[ERROR] Failed to retrieve index of network interface '%s'.\n", cfg.interface);
|
|
||||||
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_msg(&cfg, 2, 0, "Loading XDP/BPF program at '%s'...", XDP_OBJ_PATH);
|
log_msg(&cfg, 2, 0, "Loading XDP/BPF program at '%s'...", XDP_OBJ_PATH);
|
||||||
|
|
||||||
// Determine custom LibBPF log level.
|
// Determine custom LibBPF log level.
|
||||||
@@ -200,21 +186,48 @@ int main(int argc, char *argv[])
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_msg(&cfg, 2, 0, "Attaching XDP program to interface '%s'...", cfg.interface);
|
int if_idx[MAX_INTERFACES] = {0};
|
||||||
|
|
||||||
|
// Attach XDP program to interface(s).
|
||||||
|
for (int i = 0; i < cfg.interfaces_cnt; i++)
|
||||||
|
{
|
||||||
|
const char* interface = cfg.interfaces[i];
|
||||||
|
|
||||||
|
if (!interface)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_msg(&cfg, 4, 0, "Retrieving interface index for '%s'...", interface);
|
||||||
|
|
||||||
|
// Get interface index.
|
||||||
|
if_idx[i] = if_nametoindex(interface);
|
||||||
|
|
||||||
|
if (if_idx[i] < 0)
|
||||||
|
{
|
||||||
|
log_msg(&cfg, 0, 1, "[WARNING] Failed to retrieve index of network interface '%s'.\n", interface);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_msg(&cfg, 3, 0, "Interface index for '%s' => %d.", interface, if_idx[i]);
|
||||||
|
|
||||||
|
log_msg(&cfg, 2, 0, "Attaching XDP program to interface '%s'...", interface);
|
||||||
|
|
||||||
// Attach XDP program.
|
// Attach XDP program.
|
||||||
char* mode_used = NULL;
|
char* mode_used = NULL;
|
||||||
|
|
||||||
if ((ret = attach_xdp(prog, &mode_used, ifidx, 0, cli.skb, cli.offload)) != 0)
|
if ((ret = attach_xdp(prog, &mode_used, if_idx[i], 0, cli.skb, cli.offload)) != 0)
|
||||||
{
|
{
|
||||||
log_msg(&cfg, 0, 1, "[ERROR] Failed to attach XDP program to interface '%s' using available modes (%d).\n", cfg.interface, ret);
|
log_msg(&cfg, 0, 1, "[WARNING] Failed to attach XDP program to interface '%s' using available modes (%d).\n", interface, ret);
|
||||||
|
|
||||||
return EXIT_FAILURE;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode_used != NULL)
|
if (mode_used != NULL)
|
||||||
{
|
{
|
||||||
log_msg(&cfg, 1, 0, "Attached XDP program using mode '%s'...", mode_used);
|
log_msg(&cfg, 1, 0, "Attached XDP program to interface '%s' using mode '%s'...", interface, mode_used);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_msg(&cfg, 2, 0, "Retrieving BPF map FDs...");
|
log_msg(&cfg, 2, 0, "Retrieving BPF map FDs...");
|
||||||
@@ -398,27 +411,39 @@ int main(int argc, char *argv[])
|
|||||||
// Check for auto-update.
|
// Check for auto-update.
|
||||||
if (cfg.update_time > 0 && (cur_time - last_update_check) > cfg.update_time)
|
if (cfg.update_time > 0 && (cur_time - last_update_check) > cfg.update_time)
|
||||||
{
|
{
|
||||||
|
log_msg(&cfg, 6, 0, "Checking for config updates...");
|
||||||
|
|
||||||
// Check if config file have been modified
|
// Check if config file have been modified
|
||||||
if (stat(cli.cfg_file, &conf_stat) == 0 && conf_stat.st_mtime > last_config_check) {
|
if (stat(cli.cfg_file, &conf_stat) == 0 && conf_stat.st_mtime > last_config_check) {
|
||||||
|
log_msg(&cfg, 3, 0, "Config file change detected during update. Attempting to reload config...");
|
||||||
|
|
||||||
// Reload config.
|
// Reload config.
|
||||||
if ((ret = load_cfg(&cfg, cli.cfg_file, &cfg_overrides)) != 0)
|
if ((ret = load_cfg(&cfg, cli.cfg_file, 1, &cfg_overrides)) != 0)
|
||||||
{
|
{
|
||||||
log_msg(&cfg, 1, 0, "[WARNING] Failed to load config after update check (%d)...\n", ret);
|
log_msg(&cfg, 1, 0, "[WARNING] Failed to load config after update check (%d)...\n", ret);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_msg(&cfg, 4, 0, "Config reloaded successfully...");
|
||||||
|
|
||||||
|
// Make sure we set doing_stats properly.
|
||||||
|
if (!cfg.no_stats && !doing_stats)
|
||||||
|
{
|
||||||
|
doing_stats = 1;
|
||||||
|
}
|
||||||
|
else if (cfg.no_stats && doing_stats)
|
||||||
|
{
|
||||||
|
doing_stats = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_FILTERS
|
#ifdef ENABLE_FILTERS
|
||||||
// Update filters.
|
// Update filters.
|
||||||
update_filters(map_filters, &cfg);
|
update_filters(map_filters, &cfg);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Update last check timer
|
// Update last check timer
|
||||||
last_config_check = time(NULL);
|
last_config_check = time(NULL);
|
||||||
|
|
||||||
// Make sure we set doing stats if needed.
|
|
||||||
if (!cfg.no_stats && !doing_stats)
|
|
||||||
{
|
|
||||||
doing_stats = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update last updated variable.
|
// Update last updated variable.
|
||||||
@@ -452,12 +477,22 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Detach XDP program.
|
// Detach XDP program from interfaces.
|
||||||
if (attach_xdp(prog, &mode_used, ifidx, 1, cli.skb, cli.offload))
|
for (int i = 0; i < MAX_INTERFACES; i++)
|
||||||
{
|
{
|
||||||
log_msg(&cfg, 0, 1, "[ERROR] Failed to detach XDP program from interface '%s'.\n", cfg.interface);
|
const char* interface = cfg.interfaces[i];
|
||||||
|
|
||||||
return EXIT_FAILURE;
|
if (!interface)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* mode_used = NULL;
|
||||||
|
|
||||||
|
if (attach_xdp(prog, &mode_used, if_idx[i], 1, cli.skb, cli.offload))
|
||||||
|
{
|
||||||
|
log_msg(&cfg, 0, 0, "[WARNING] Failed to detach XDP program from interface '%s'.\n", interface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpin maps from file system.
|
// Unpin maps from file system.
|
||||||
|
|||||||
@@ -5,14 +5,20 @@
|
|||||||
*
|
*
|
||||||
* @param cfg A pointer to the config structure.
|
* @param cfg A pointer to the config structure.
|
||||||
* @param cfg_file The path to the config file.
|
* @param cfg_file The path to the config file.
|
||||||
|
* @param load_defaults Whether to load defaults or not.
|
||||||
* @param overrides Overrides to use instead of config values.
|
* @param overrides Overrides to use instead of config values.
|
||||||
*
|
*
|
||||||
* @return 0 on success or 1 on error.
|
* @return 0 on success or 1 on error.
|
||||||
*/
|
*/
|
||||||
int load_cfg(config__t *cfg, const char* cfg_file, config_overrides_t* overrides)
|
int load_cfg(config__t *cfg, const char* cfg_file, int load_defaults, config_overrides_t* overrides)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (load_defaults)
|
||||||
|
{
|
||||||
|
set_cfg_defaults(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
FILE *file = NULL;
|
FILE *file = NULL;
|
||||||
|
|
||||||
// Open config file.
|
// Open config file.
|
||||||
@@ -23,8 +29,6 @@ int load_cfg(config__t *cfg, const char* cfg_file, config_overrides_t* overrides
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_cfg_defaults(cfg);
|
|
||||||
|
|
||||||
char* buffer = NULL;
|
char* buffer = NULL;
|
||||||
|
|
||||||
// Read config.
|
// Read config.
|
||||||
@@ -205,25 +209,68 @@ int parse_cfg(config__t *cfg, const char* data, config_overrides_t* overrides)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get interface.
|
// Get interface(s).
|
||||||
const char *interface;
|
config_setting_t* interfaces = config_lookup(&conf, "interfaces");
|
||||||
|
|
||||||
if (config_lookup_string(&conf, "interface", &interface) == CONFIG_TRUE || (overrides && overrides->interface != NULL))
|
if (interfaces)
|
||||||
{
|
{
|
||||||
// We must free previous value to prevent memory leak.
|
if (config_setting_is_list(interfaces))
|
||||||
if (cfg->interface != NULL)
|
|
||||||
{
|
{
|
||||||
free(cfg->interface);
|
for (int i = 0; i < config_setting_length(interfaces); i++)
|
||||||
cfg->interface = NULL;
|
{
|
||||||
|
if (i >= MAX_INTERFACES)
|
||||||
|
{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overrides && overrides->interface != NULL)
|
const char* interface = config_setting_get_string_elem(interfaces, i);
|
||||||
|
|
||||||
|
if (!interface)
|
||||||
{
|
{
|
||||||
cfg->interface = strdup(overrides->interface);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg->interfaces[i])
|
||||||
|
{
|
||||||
|
free(cfg->interfaces[i]);
|
||||||
|
cfg->interfaces[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 0 && overrides && overrides->interface)
|
||||||
|
{
|
||||||
|
cfg->interfaces[i] = strdup(overrides->interface);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cfg->interface = strdup(interface);
|
cfg->interfaces[i] = strdup(interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg->interfaces_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char* interface;
|
||||||
|
|
||||||
|
if (config_lookup_string(&conf, "interfaces", &interface) == CONFIG_TRUE)
|
||||||
|
{
|
||||||
|
if (cfg->interfaces[0])
|
||||||
|
{
|
||||||
|
free(cfg->interfaces[0]);
|
||||||
|
cfg->interfaces[0] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overrides && overrides->interface)
|
||||||
|
{
|
||||||
|
cfg->interfaces[0] = strdup(overrides->interface);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cfg->interfaces[0] = strdup(interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg->interfaces_cnt = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,6 +367,8 @@ int parse_cfg(config__t *cfg, const char* data, config_overrides_t* overrides)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg->filters_cnt++;
|
||||||
|
|
||||||
// Make sure filter is set.
|
// Make sure filter is set.
|
||||||
filter->set = 1;
|
filter->set = 1;
|
||||||
|
|
||||||
@@ -562,6 +611,7 @@ int parse_cfg(config__t *cfg, const char* data, config_overrides_t* overrides)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ICMP options */
|
/* ICMP options */
|
||||||
|
|
||||||
// Enabled.
|
// Enabled.
|
||||||
int icmp_enabled;
|
int icmp_enabled;
|
||||||
|
|
||||||
@@ -599,16 +649,20 @@ int parse_cfg(config__t *cfg, const char* data, config_overrides_t* overrides)
|
|||||||
|
|
||||||
if (cfg->drop_ranges[i])
|
if (cfg->drop_ranges[i])
|
||||||
{
|
{
|
||||||
free((void*)cfg->drop_ranges[i]);
|
free(cfg->drop_ranges[i]);
|
||||||
cfg->drop_ranges[i] = NULL;
|
cfg->drop_ranges[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* new_range = config_setting_get_string_elem(setting, i);
|
const char* new_range = config_setting_get_string_elem(setting, i);
|
||||||
|
|
||||||
if (new_range)
|
if (!new_range)
|
||||||
{
|
{
|
||||||
cfg->drop_ranges[i] = strdup(new_range);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg->drop_ranges[i] = strdup(new_range);
|
||||||
|
|
||||||
|
cfg->drop_ranges_cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,11 +700,36 @@ int save_cfg(config__t* cfg, const char* file_path)
|
|||||||
config_setting_set_string(setting, cfg->log_file);
|
config_setting_set_string(setting, cfg->log_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add interface.
|
// Add interface(s).
|
||||||
if (cfg->interface)
|
if (cfg->interfaces_cnt > 0)
|
||||||
{
|
{
|
||||||
setting = config_setting_add(root, "interface", CONFIG_TYPE_STRING);
|
if (cfg->interfaces_cnt > 1)
|
||||||
config_setting_set_string(setting, cfg->interface);
|
{
|
||||||
|
setting = config_setting_add(root, "interfaces", CONFIG_TYPE_LIST);
|
||||||
|
|
||||||
|
for (int i = 0; i < cfg->interfaces_cnt; i++)
|
||||||
|
{
|
||||||
|
const char* interface = cfg->interfaces[i];
|
||||||
|
|
||||||
|
if (!interface)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
config_setting_t* setting_interface = config_setting_add(setting, NULL, CONFIG_TYPE_STRING);
|
||||||
|
config_setting_set_string(setting_interface, interface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char* interface = cfg->interfaces[0];
|
||||||
|
|
||||||
|
if (interface)
|
||||||
|
{
|
||||||
|
setting = config_setting_add(root, "interfaces", CONFIG_TYPE_STRING);
|
||||||
|
config_setting_set_string(setting, interface);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add pin maps.
|
// Add pin maps.
|
||||||
@@ -980,28 +1059,28 @@ void set_filter_defaults(filter_rule_cfg_t* filter)
|
|||||||
|
|
||||||
if (filter->ip.src_ip)
|
if (filter->ip.src_ip)
|
||||||
{
|
{
|
||||||
free((void*)filter->ip.src_ip);
|
free(filter->ip.src_ip);
|
||||||
|
|
||||||
filter->ip.src_ip = NULL;
|
filter->ip.src_ip = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter->ip.dst_ip)
|
if (filter->ip.dst_ip)
|
||||||
{
|
{
|
||||||
free((void*)filter->ip.dst_ip);
|
free(filter->ip.dst_ip);
|
||||||
|
|
||||||
filter->ip.dst_ip = NULL;
|
filter->ip.dst_ip = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter->ip.src_ip6)
|
if (filter->ip.src_ip6)
|
||||||
{
|
{
|
||||||
free((void*)filter->ip.src_ip6);
|
free(filter->ip.src_ip6);
|
||||||
|
|
||||||
filter->ip.src_ip6 = NULL;
|
filter->ip.src_ip6 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter->ip.dst_ip6)
|
if (filter->ip.dst_ip6)
|
||||||
{
|
{
|
||||||
free((void*)filter->ip.dst_ip6);
|
free(filter->ip.dst_ip6);
|
||||||
|
|
||||||
filter->ip.dst_ip6 = NULL;
|
filter->ip.dst_ip6 = NULL;
|
||||||
}
|
}
|
||||||
@@ -1047,14 +1126,39 @@ void set_filter_defaults(filter_rule_cfg_t* filter)
|
|||||||
void set_cfg_defaults(config__t* cfg)
|
void set_cfg_defaults(config__t* cfg)
|
||||||
{
|
{
|
||||||
cfg->verbose = 2;
|
cfg->verbose = 2;
|
||||||
cfg->log_file = strdup("/var/log/xdpfw.log");
|
|
||||||
cfg->update_time = 0;
|
cfg->update_time = 0;
|
||||||
cfg->interface = NULL;
|
|
||||||
cfg->pin_maps = 1;
|
cfg->pin_maps = 1;
|
||||||
cfg->no_stats = 0;
|
cfg->no_stats = 0;
|
||||||
cfg->stats_per_second = 0;
|
cfg->stats_per_second = 0;
|
||||||
cfg->stdout_update_time = 1000;
|
cfg->stdout_update_time = 1000;
|
||||||
|
|
||||||
|
if (cfg->log_file)
|
||||||
|
{
|
||||||
|
free(cfg->log_file);
|
||||||
|
|
||||||
|
cfg->log_file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg->log_file = strdup("/var/log/xdpfw.log");
|
||||||
|
|
||||||
|
cfg->interfaces_cnt = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_INTERFACES; i++)
|
||||||
|
{
|
||||||
|
char* interface = cfg->interfaces[i];
|
||||||
|
|
||||||
|
if (!interface)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(interface);
|
||||||
|
|
||||||
|
cfg->interfaces[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg->filters_cnt = 0;
|
||||||
|
|
||||||
for (int i = 0; i < MAX_FILTERS; i++)
|
for (int i = 0; i < MAX_FILTERS; i++)
|
||||||
{
|
{
|
||||||
filter_rule_cfg_t* filter = &cfg->filters[i];
|
filter_rule_cfg_t* filter = &cfg->filters[i];
|
||||||
@@ -1062,7 +1166,21 @@ void set_cfg_defaults(config__t* cfg)
|
|||||||
set_filter_defaults(filter);
|
set_filter_defaults(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(cfg->drop_ranges, 0, sizeof(cfg->drop_ranges));
|
cfg->drop_ranges_cnt = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_IP_RANGES; i++)
|
||||||
|
{
|
||||||
|
char* drop_range = cfg->drop_ranges[i];
|
||||||
|
|
||||||
|
if (!drop_range)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(drop_range);
|
||||||
|
|
||||||
|
cfg->drop_ranges[i] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1169,14 +1287,7 @@ void print_filter(filter_rule_cfg_t* filter, int idx)
|
|||||||
*/
|
*/
|
||||||
void print_cfg(config__t* cfg)
|
void print_cfg(config__t* cfg)
|
||||||
{
|
{
|
||||||
char* interface = "N/A";
|
const char* log_file = "N/A";
|
||||||
|
|
||||||
if (cfg->interface != NULL)
|
|
||||||
{
|
|
||||||
interface = cfg->interface;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* log_file = "N/A";
|
|
||||||
|
|
||||||
if (cfg->log_file != NULL)
|
if (cfg->log_file != NULL)
|
||||||
{
|
{
|
||||||
@@ -1185,19 +1296,42 @@ void print_cfg(config__t* cfg)
|
|||||||
|
|
||||||
printf("Printing config...\n");
|
printf("Printing config...\n");
|
||||||
printf("General Settings\n");
|
printf("General Settings\n");
|
||||||
|
|
||||||
printf("\tVerbose => %d\n", cfg->verbose);
|
printf("\tVerbose => %d\n", cfg->verbose);
|
||||||
printf("\tLog File => %s\n", log_file);
|
printf("\tLog File => %s\n", log_file);
|
||||||
printf("\tInterface Name => %s\n", interface);
|
|
||||||
printf("\tPin BPF Maps => %d\n", cfg->pin_maps);
|
printf("\tPin BPF Maps => %d\n", cfg->pin_maps);
|
||||||
printf("\tUpdate Time => %d\n", cfg->update_time);
|
printf("\tUpdate Time => %d\n", cfg->update_time);
|
||||||
printf("\tNo Stats => %d\n", cfg->no_stats);
|
printf("\tNo Stats => %d\n", cfg->no_stats);
|
||||||
printf("\tStats Per Second => %d\n", cfg->stats_per_second);
|
printf("\tStats Per Second => %d\n", cfg->stats_per_second);
|
||||||
printf("\tStdout Update Time => %d\n\n", cfg->stdout_update_time);
|
printf("\tStdout Update Time => %d\n\n", cfg->stdout_update_time);
|
||||||
|
|
||||||
|
printf("Interfaces\n");
|
||||||
|
|
||||||
|
if (cfg->interfaces_cnt > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cfg->interfaces_cnt; i++)
|
||||||
|
{
|
||||||
|
const char* interface = cfg->interfaces[i];
|
||||||
|
|
||||||
|
if (!interface)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\t- %s\n", interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\t- None\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
printf("Filters\n");
|
printf("Filters\n");
|
||||||
|
|
||||||
for (int i = 0; i < MAX_FILTERS; i++)
|
if (cfg->filters_cnt > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cfg->filters_cnt; i++)
|
||||||
{
|
{
|
||||||
filter_rule_cfg_t *filter = &cfg->filters[i];
|
filter_rule_cfg_t *filter = &cfg->filters[i];
|
||||||
|
|
||||||
@@ -1212,18 +1346,32 @@ void print_cfg(config__t* cfg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\t- None\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
printf("IP Drop Ranges\n");
|
printf("IP Drop Ranges\n");
|
||||||
|
|
||||||
for (int i = 0; i < MAX_IP_RANGES; i++)
|
if (cfg->drop_ranges_cnt > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cfg->drop_ranges_cnt; i++)
|
||||||
{
|
{
|
||||||
const char* range = cfg->drop_ranges[i];
|
const char* range = cfg->drop_ranges[i];
|
||||||
|
|
||||||
if (range)
|
if (!range)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
printf("\t- %s\n", range);
|
printf("\t- %s\n", range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\t- None\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,11 +15,11 @@
|
|||||||
|
|
||||||
struct filter_rule_ip_opts
|
struct filter_rule_ip_opts
|
||||||
{
|
{
|
||||||
const char* src_ip;
|
char* src_ip;
|
||||||
const char* dst_ip;
|
char* dst_ip;
|
||||||
|
|
||||||
const char* src_ip6;
|
char* src_ip6;
|
||||||
const char* dst_ip6;
|
char* dst_ip6;
|
||||||
|
|
||||||
int min_ttl;
|
int min_ttl;
|
||||||
int max_ttl;
|
int max_ttl;
|
||||||
@@ -86,15 +86,20 @@ struct config
|
|||||||
{
|
{
|
||||||
int verbose;
|
int verbose;
|
||||||
char *log_file;
|
char *log_file;
|
||||||
char *interface;
|
|
||||||
unsigned int pin_maps : 1;
|
unsigned int pin_maps : 1;
|
||||||
int update_time;
|
int update_time;
|
||||||
unsigned int no_stats : 1;
|
unsigned int no_stats : 1;
|
||||||
unsigned int stats_per_second : 1;
|
unsigned int stats_per_second : 1;
|
||||||
int stdout_update_time;
|
int stdout_update_time;
|
||||||
|
|
||||||
|
int interfaces_cnt;
|
||||||
|
char* interfaces[MAX_INTERFACES];
|
||||||
|
|
||||||
|
int filters_cnt;
|
||||||
filter_rule_cfg_t filters[MAX_FILTERS];
|
filter_rule_cfg_t filters[MAX_FILTERS];
|
||||||
const char* drop_ranges[MAX_IP_RANGES];
|
|
||||||
|
int drop_ranges_cnt;
|
||||||
|
char* drop_ranges[MAX_IP_RANGES];
|
||||||
} typedef config__t; // config_t is taken by libconfig -.-
|
} typedef config__t; // config_t is taken by libconfig -.-
|
||||||
|
|
||||||
struct config_overrides
|
struct config_overrides
|
||||||
@@ -115,7 +120,7 @@ void set_filter_defaults(filter_rule_cfg_t* filter);
|
|||||||
void print_cfg(config__t* cfg);
|
void print_cfg(config__t* cfg);
|
||||||
void print_filter(filter_rule_cfg_t* filter, int idx);
|
void print_filter(filter_rule_cfg_t* filter, int idx);
|
||||||
|
|
||||||
int load_cfg(config__t *cfg, const char* cfg_file, config_overrides_t* overrides);
|
int load_cfg(config__t *cfg, const char* cfg_file, int load_defaults, config_overrides_t* overrides);
|
||||||
int save_cfg(config__t* cfg, const char* file_path);
|
int save_cfg(config__t* cfg, const char* file_path);
|
||||||
|
|
||||||
int open_cfg(FILE** file, const char *file_name);
|
int open_cfg(FILE** file, const char *file_name);
|
||||||
|
|||||||
@@ -473,7 +473,7 @@ void update_filters(int map_filters, config__t *cfg)
|
|||||||
int cur_idx = 0;
|
int cur_idx = 0;
|
||||||
|
|
||||||
// Add a filter to the filter maps.
|
// Add a filter to the filter maps.
|
||||||
for (int i = 0; i < MAX_FILTERS; i++)
|
for (int i = 0; i < cfg->filters_cnt; i++)
|
||||||
{
|
{
|
||||||
// Delete previous rule from BPF map.
|
// 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.
|
// 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.
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (cli.save || cli.mode == 0)
|
if (cli.save || cli.mode == 0)
|
||||||
{
|
{
|
||||||
if ((ret = load_cfg(&cfg, cli.cfg_file, NULL)) != 0)
|
if ((ret = load_cfg(&cfg, cli.cfg_file, 1, NULL)) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[ERROR] Failed to load config at '%s' (%d)\n", cli.cfg_file, ret);
|
fprintf(stderr, "[ERROR] Failed to load config at '%s' (%d)\n", cli.cfg_file, ret);
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
struct cli
|
struct cli
|
||||||
{
|
{
|
||||||
const char* cfg_file;
|
char* cfg_file;
|
||||||
|
|
||||||
int help;
|
int help;
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ struct cli
|
|||||||
|
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
const char* ip;
|
char* ip;
|
||||||
int v6;
|
int v6;
|
||||||
|
|
||||||
s64 expires;
|
s64 expires;
|
||||||
@@ -30,11 +30,11 @@ struct cli
|
|||||||
int action;
|
int action;
|
||||||
s64 block_time;
|
s64 block_time;
|
||||||
|
|
||||||
const char* src_ip;
|
char* src_ip;
|
||||||
const char* dst_ip;
|
char* dst_ip;
|
||||||
|
|
||||||
const char* src_ip6;
|
char* src_ip6;
|
||||||
const char* dst_ip6;
|
char* dst_ip6;
|
||||||
|
|
||||||
s64 pps;
|
s64 pps;
|
||||||
s64 bps;
|
s64 bps;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (cli.save || cli.mode == 0)
|
if (cli.save || cli.mode == 0)
|
||||||
{
|
{
|
||||||
if ((ret = load_cfg(&cfg, cli.cfg_file, NULL)) != 0)
|
if ((ret = load_cfg(&cfg, cli.cfg_file, 1, NULL)) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[ERROR] Failed to load config at '%s' (%d)\n", cli.cfg_file, ret);
|
fprintf(stderr, "[ERROR] Failed to load config at '%s' (%d)\n", cli.cfg_file, ret);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user