Restructure project and organize code.

This commit is contained in:
Christian Deacon
2025-02-22 09:50:57 -05:00
parent e3d47fda6f
commit 8756892791
25 changed files with 403 additions and 334 deletions

View File

@@ -0,0 +1,72 @@
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include "cmdline.h"
const struct option opts[] =
{
{"config", required_argument, NULL, 'c'},
{"offload", no_argument, NULL, 'o'},
{"skb", no_argument, NULL, 's'},
{"time", required_argument, NULL, 't'},
{"list", no_argument, NULL, 'l'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
/**
* Parses the command line and stores values in the cmdline structure.
*
* @param cmd A pointer to the cmdline structure.
*
* @return Void
*/
void ParseCommandLine(struct cmdline *cmd, int argc, char *argv[])
{
int c;
while ((c = getopt_long(argc, argv, "c:ost:lh", opts, NULL)) != -1)
{
switch (c)
{
case 'c':
cmd->cfgfile = optarg;
break;
case 'o':
cmd->offload = 1;
break;
case 's':
cmd->skb = 1;
break;
case 't':
cmd->time = atoi(optarg);
break;
case 'l':
cmd->list = 1;
break;
case 'h':
cmd->help = 1;
break;
case '?':
fprintf(stderr, "Missing argument option...\n");
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,13 @@
#pragma once
struct cmdline
{
char *cfgfile;
unsigned int offload : 1;
unsigned int skb : 1;
unsigned int time;
unsigned int list : 1;
unsigned int help : 1;
};
void ParseCommandLine(struct cmdline *cmd, int argc, char *argv[]);

511
src/loader/utils/config.c Normal file
View File

@@ -0,0 +1,511 @@
#include <loader/utils/config.h>
#include <loader/utils/helpers.h>
FILE *file;
/**
* Sets the config structure's default values.
*
* @param cfg A pointer to the config structure.
*
* @return Void
*/
void SetCfgDefaults(struct config *cfg)
{
cfg->updatetime = 0;
cfg->interface = NULL;
cfg->nostats = 0;
cfg->stdout_update_time = 1000;
for (u16 i = 0; i < MAX_FILTERS; i++)
{
cfg->filters[i].id = 0;
cfg->filters[i].enabled = 0;
cfg->filters[i].action = 0;
cfg->filters[i].src_ip = 0;
cfg->filters[i].dst_ip = 0;
for (u8 j = 0; j < 4; j++)
{
cfg->filters[i].src_ip6[j] = 0;
cfg->filters[i].dst_ip6[j] = 0;
}
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].do_pps = 0;
cfg->filters[i].pps = 0;
cfg->filters[i].do_bps = 0;
cfg->filters[i].bps = 0;
cfg->filters[i].blocktime = 1;
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].tcpopts.do_ece = 0;
cfg->filters[i].tcpopts.do_cwr = 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;
}
}
/**
* Opens the config file.
*
* @param filename Path to config file.
*
* @return 0 on success or 1 on error.
*/
int OpenCfg(const char *filename)
{
// Close any existing files.
if (file != NULL)
{
fclose(file);
file = NULL;
}
file = fopen(filename, "r");
if (file == NULL)
{
return 1;
}
return 0;
}
/**
* Read the config file and stores values in config structure.
*
* @param cfg A pointer to the config structure.
*
* @return 0 on success or 1/-1 on error.
*/
int ReadCfg(struct config *cfg)
{
// 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;
config_init(&conf);
// Attempt to read the config.
if (config_read(&conf, file) == CONFIG_FALSE)
{
fprintf(stderr, "Error from LibConfig when reading file - %s (Line %d)\n\n", config_error_text(&conf), config_error_line(&conf));
config_destroy(&conf);
return 1;
}
// Get interface.
const char *interface;
if (!config_lookup_string(&conf, "interface", &interface))
{
fprintf(stderr, "Error from LibConfig when reading 'interface' setting - %s\n\n", config_error_text(&conf));
config_destroy(&conf);
return 1;
}
cfg->interface = strdup(interface);
// Get auto update time.
int updatetime;
if (config_lookup_int(&conf, "update_time", &updatetime) == CONFIG_TRUE)
{
cfg->updatetime = updatetime;
}
// Get stdout update time.
int stdout_update_time;
if (config_lookup_int(&conf, "stdout_update_time", &stdout_update_time) == CONFIG_TRUE)
{
cfg->stdout_update_time = stdout_update_time;
}
// Get no stats.
int nostats;
if (config_lookup_bool(&conf, "no_stats", &nostats) == CONFIG_TRUE)
{
cfg->nostats = nostats;
}
// Read filters in filters_map structure.
setting = config_lookup(&conf, "filters");
// Check if filters map is valid. If not, not a biggie since they aren't required.
if (setting == NULL)
{
fprintf(stderr, "Error from LibConfig when reading 'filters' array - %s\n\n", config_error_text(&conf));
config_destroy(&conf);
return 1;
}
// Set filter count.
int filters = 0;
for (u8 i = 0; i < config_setting_length(setting); i++)
{
config_setting_t* filter = config_setting_get_elem(setting, i);
// Enabled.
int enabled;
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));
continue;
}
cfg->filters[i].enabled = enabled;
// Action (required).
int action;
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));
cfg->filters[i].enabled = 0;
continue;
}
cfg->filters[i].action = action;
// Source IP (not required).
const char *sip;
if (config_setting_lookup_string(filter, "src_ip", &sip))
{
struct ip ip = ParseIp(sip);
cfg->filters[i].src_ip = ip.ip;
cfg->filters[i].src_cidr = ip.cidr;
}
// Destination IP (not required).
const char *dip;
if (config_setting_lookup_string(filter, "dst_ip", &dip))
{
struct ip ip = ParseIp(dip);
cfg->filters[i].dst_ip = ip.ip;
cfg->filters[i].dst_cidr = ip.cidr;
}
// Source IP (IPv6) (not required).
const char *sip6;
if (config_setting_lookup_string(filter, "src_ip6", &sip6))
{
struct in6_addr in;
inet_pton(AF_INET6, sip6, &in);
for (u8 j = 0; j < 4; j++)
{
cfg->filters[i].src_ip6[j] = in.__in6_u.__u6_addr32[j];
}
}
// Destination IP (IPv6) (not required).
const char *dip6;
if (config_setting_lookup_string(filter, "dst_ip6", &dip6))
{
struct in6_addr in;
inet_pton(AF_INET6, dip6, &in);
for (u8 j = 0; j < 4; j++)
{
cfg->filters[i].dst_ip6[j] = in.__in6_u.__u6_addr32[j];
}
}
// Minimum TTL (not required).
int min_ttl;
if (config_setting_lookup_int(filter, "min_ttl", &min_ttl))
{
cfg->filters[i].min_ttl = (u8)min_ttl;
cfg->filters[i].do_min_ttl = 1;
}
// Maximum TTL (not required).
int max_ttl;
if (config_setting_lookup_int(filter, "max_ttl", &max_ttl))
{
cfg->filters[i].max_ttl = (u8)max_ttl;
cfg->filters[i].do_max_ttl = 1;
}
// Minimum length (not required).
int min_len;
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).
int max_len;
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).
int tos;
if (config_setting_lookup_int(filter, "tos", &tos))
{
cfg->filters[i].tos = (u8)tos;
cfg->filters[i].do_tos = 1;
}
// PPS (not required).
long long pps;
if (config_setting_lookup_int64(filter, "pps", &pps))
{
cfg->filters[i].pps = pps;
cfg->filters[i].do_pps = 1;
}
// BPS (not required).
long long bps;
if (config_setting_lookup_int64(filter, "bps", &bps))
{
cfg->filters[i].bps = bps;
cfg->filters[i].do_bps = 1;
}
// Block time (default 1).
long long blocktime;
if (config_setting_lookup_int64(filter, "block_time", &blocktime))
{
cfg->filters[i].blocktime = blocktime;
}
else
{
cfg->filters[i].blocktime = 1;
}
/* TCP options */
// Enabled.
int tcpenabled;
if (config_setting_lookup_bool(filter, "tcp_enabled", &tcpenabled))
{
cfg->filters[i].tcpopts.enabled = tcpenabled;
}
// Source port.
long long tcpsport;
if (config_setting_lookup_int64(filter, "tcp_sport", &tcpsport))
{
cfg->filters[i].tcpopts.sport = (u16)tcpsport;
cfg->filters[i].tcpopts.do_sport = 1;
}
// Destination port.
long long tcpdport;
if (config_setting_lookup_int64(filter, "tcp_dport", &tcpdport))
{
cfg->filters[i].tcpopts.dport = (u16)tcpdport;
cfg->filters[i].tcpopts.do_dport = 1;
}
// URG flag.
int tcpurg;
if (config_setting_lookup_bool(filter, "tcp_urg", &tcpurg))
{
cfg->filters[i].tcpopts.urg = tcpurg;
cfg->filters[i].tcpopts.do_urg = 1;
}
// ACK flag.
int tcpack;
if (config_setting_lookup_bool(filter, "tcp_ack", &tcpack))
{
cfg->filters[i].tcpopts.ack = tcpack;
cfg->filters[i].tcpopts.do_ack = 1;
}
// RST flag.
int tcprst;
if (config_setting_lookup_bool(filter, "tcp_rst", &tcprst))
{
cfg->filters[i].tcpopts.rst = tcprst;
cfg->filters[i].tcpopts.do_rst = 1;
}
// PSH flag.
int tcppsh;
if (config_setting_lookup_bool(filter, "tcp_psh", &tcppsh))
{
cfg->filters[i].tcpopts.psh = tcppsh;
cfg->filters[i].tcpopts.do_psh = 1;
}
// SYN flag.
int tcpsyn;
if (config_setting_lookup_bool(filter, "tcp_syn", &tcpsyn))
{
cfg->filters[i].tcpopts.syn = tcpsyn;
cfg->filters[i].tcpopts.do_syn = 1;
}
// FIN flag.
int tcpfin;
if (config_setting_lookup_bool(filter, "tcp_fin", &tcpfin))
{
cfg->filters[i].tcpopts.fin = tcpfin;
cfg->filters[i].tcpopts.do_fin = 1;
}
// ECE flag.
int tcpece;
if (config_setting_lookup_bool(filter, "tcp_ece", &tcpece))
{
cfg->filters[i].tcpopts.ece = tcpece;
cfg->filters[i].tcpopts.do_ece = 1;
}
// CWR flag.
int tcpcwr;
if (config_setting_lookup_bool(filter, "tcp_cwr", &tcpcwr))
{
cfg->filters[i].tcpopts.cwr = tcpcwr;
cfg->filters[i].tcpopts.do_cwr = 1;
}
/* UDP options */
// Enabled.
int udpenabled;
if (config_setting_lookup_bool(filter, "udp_enabled", &udpenabled))
{
cfg->filters[i].udpopts.enabled = udpenabled;
}
// Source port.
long long udpsport;
if (config_setting_lookup_int64(filter, "udp_sport", &udpsport))
{
cfg->filters[i].udpopts.sport = (u16)udpsport;
cfg->filters[i].udpopts.do_sport = 1;
}
// Destination port.
long long udpdport;
if (config_setting_lookup_int64(filter, "udp_dport", &udpdport))
{
cfg->filters[i].udpopts.dport = (u16)udpdport;
cfg->filters[i].udpopts.do_dport = 1;
}
/* ICMP options */
// Enabled.
int icmpenabled;
if (config_setting_lookup_bool(filter, "icmp_enabled", &icmpenabled))
{
cfg->filters[i].icmpopts.enabled = icmpenabled;
}
// ICMP code.
int icmpcode;
if (config_setting_lookup_int(filter, "icmp_code", &icmpcode))
{
cfg->filters[i].icmpopts.code = (u8)icmpcode;
cfg->filters[i].icmpopts.do_code = 1;
}
// ICMP type.
int icmptype;
if (config_setting_lookup_int(filter, "icmp_type", &icmptype))
{
cfg->filters[i].icmpopts.type = (u8)icmptype;
cfg->filters[i].icmpopts.do_type = 1;
}
// Assign ID and increase filter count.
cfg->filters[i].id = ++filters;
}
config_destroy(&conf);
return 0;
}

24
src/loader/utils/config.h Normal file
View File

@@ -0,0 +1,24 @@
#pragma once
#include <common/all.h>
#include <stdio.h>
#include <stdlib.h>
#include <libconfig.h>
#include <string.h>
#include <linux/types.h>
#include <arpa/inet.h>
struct config
{
char *interface;
u16 updatetime;
unsigned int nostats : 1;
int stdout_update_time;
struct filter filters[MAX_FILTERS];
};
void SetCfgDefaults(struct config *cfg);
int OpenCfg(const char *filename);
int ReadCfg(struct config *cfg);

View File

@@ -0,0 +1,30 @@
#include <loader/utils/helpers.h>
/**
* Parses an IP string with CIDR support. Stores IP in network byte order in ip.ip and CIDR in ip.cidr.
*
* @param ip The IP string.
*
* @return Returns an IP structure with IP and CIDR.
*/
struct ip ParseIp(const char *ip)
{
struct ip ret = {0};
ret.cidr = 32;
char *token = strtok((char *) ip, "/");
if (token)
{
ret.ip = inet_addr(token);
token = strtok(NULL, "/");
if (token)
{
ret.cidr = (unsigned int) strtoul(token, NULL, 10);
}
}
return ret;
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <common/all.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
struct ip
{
u32 ip;
u32 cidr;
};
struct ip ParseIp(const char *ip);