Checkpoint (close to finished).
This commit is contained in:
12
src/config.c
12
src/config.c
@@ -14,6 +14,7 @@ void SetConfigDefaults(struct config_map *cfg)
|
||||
{
|
||||
cfg->updateTime = 0;
|
||||
cfg->interface = "eth0";
|
||||
cfg->nostats = 0;
|
||||
|
||||
for (uint16_t i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
@@ -138,6 +139,14 @@ int ReadConfig(struct config_map *cfg)
|
||||
|
||||
cfg->updateTime = updateTime;
|
||||
|
||||
// Get no stats.
|
||||
int nostats;
|
||||
|
||||
if (config_lookup_bool(&conf, "nostats", &nostats) == CONFIG_TRUE)
|
||||
{
|
||||
cfg->nostats = nostats;
|
||||
}
|
||||
|
||||
// Read filters in filters_map structure.
|
||||
setting = config_lookup(&conf, "filters");
|
||||
|
||||
@@ -444,9 +453,6 @@ int ReadConfig(struct config_map *cfg)
|
||||
filters++;
|
||||
}
|
||||
|
||||
// Assign filter count to config.
|
||||
cfg->filterCount = filters;
|
||||
|
||||
config_destroy(&conf);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -7,7 +7,7 @@ struct config_map
|
||||
{
|
||||
char *interface;
|
||||
uint16_t updateTime;
|
||||
uint16_t filterCount;
|
||||
unsigned int nostats : 1;
|
||||
struct filter filters[MAX_FILTERS];
|
||||
};
|
||||
|
||||
|
||||
@@ -50,14 +50,6 @@ struct bpf_map_def SEC("maps") filters_map =
|
||||
.max_entries = MAX_FILTERS
|
||||
};
|
||||
|
||||
struct bpf_map_def SEC("maps") count_map =
|
||||
{
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(uint32_t),
|
||||
.value_size = sizeof(uint8_t),
|
||||
.max_entries = 1
|
||||
};
|
||||
|
||||
struct bpf_map_def SEC("maps") stats_map =
|
||||
{
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
@@ -69,30 +61,6 @@ struct bpf_map_def SEC("maps") stats_map =
|
||||
SEC("xdp_prog")
|
||||
int xdp_prog_main(struct xdp_md *ctx)
|
||||
{
|
||||
// Check for count map.
|
||||
uint32_t key = 0;
|
||||
uint16_t *filters;
|
||||
|
||||
filters = bpf_map_lookup_elem(&count_map, &key);
|
||||
|
||||
// Check if the count map value is valid.
|
||||
if (filters == NULL)
|
||||
{
|
||||
return XDP_ABORTED;
|
||||
}
|
||||
|
||||
// Filter count.
|
||||
uint8_t filterCount;
|
||||
|
||||
if (*filters > MAX_FILTERS)
|
||||
{
|
||||
filterCount = MAX_FILTERS;
|
||||
}
|
||||
else
|
||||
{
|
||||
filterCount = *filters;
|
||||
}
|
||||
|
||||
// Initialize data.
|
||||
void *data_end = (void *)(long)ctx->data_end;
|
||||
void *data = (void *)(long)ctx->data;
|
||||
@@ -189,11 +157,13 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
|
||||
for (uint8_t i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
// Check if ID is above 0 (if 0, it's an invalid rule).
|
||||
if (!filter[i] || filter[i]->id < 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if the rule is enabled.
|
||||
if (!filter[i]->enabled)
|
||||
{
|
||||
continue;
|
||||
@@ -241,17 +211,20 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Custom payload.
|
||||
// Payload match.
|
||||
if (filter[i]->payloadLen > 0)
|
||||
{
|
||||
// Initialize packet data.
|
||||
uint8_t *pcktData = (data + sizeof(struct ethhdr) + (iph->ihl * 4) + l4headerLen);
|
||||
|
||||
// Now check packet data and ensure we have enough to match.
|
||||
if (pcktData + (filter[i]->payloadLen + 1) > (uint8_t *)data_end)
|
||||
if (pcktData + (filter[i]->payloadLen) > (uint8_t *)data_end)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t found = 1;
|
||||
|
||||
for (uint16_t j = 0; j < filter[i]->payloadLen; j++)
|
||||
{
|
||||
if ((*pcktData++) == filter[i]->payloadMatch[j])
|
||||
@@ -259,8 +232,15 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
continue;
|
||||
}
|
||||
|
||||
found = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Check layer 4 filters.
|
||||
@@ -370,7 +350,32 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
|
||||
if (matched)
|
||||
{
|
||||
// Get stats map.
|
||||
uint32_t key = 0;
|
||||
struct xdpfw_stats *stats;
|
||||
|
||||
stats = bpf_map_lookup_elem(&stats_map, &key);
|
||||
|
||||
if (stats)
|
||||
{
|
||||
// Update stats map.
|
||||
if (action == 0)
|
||||
{
|
||||
stats->blocked++;
|
||||
}
|
||||
else
|
||||
{
|
||||
stats->allowed++;
|
||||
}
|
||||
|
||||
key = 0;
|
||||
|
||||
bpf_map_update_elem(&stats_map, &key, stats, BPF_ANY);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bpf_printk("Matched with protocol %" PRIu8 " and sAddr %" PRIu32 "\n", iph->protocol, iph->saddr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ const struct option opts[] =
|
||||
// Other variables.
|
||||
static uint8_t cont = 1;
|
||||
static int filter_map_fd = -1;
|
||||
static int count_map_fd = -1;
|
||||
static int stats_map_fd = -1;
|
||||
|
||||
void signalHndl(int tmp)
|
||||
@@ -87,8 +86,15 @@ void update_BPF(struct config_map *conf)
|
||||
}
|
||||
|
||||
// Add a filter to the filter maps.
|
||||
for (uint32_t i = 0; i < conf->filterCount; i++)
|
||||
for (uint32_t i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
// Check if we have a valid ID.
|
||||
if (conf->filters[i].id < 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Attempt to update BPF map.
|
||||
if (bpf_map_update_elem(filter_map_fd, &i, &conf->filters[i], BPF_ANY) == -1)
|
||||
{
|
||||
fprintf(stderr, "Error updating BPF item #%d\n", i);
|
||||
@@ -161,7 +167,6 @@ int load_bpf_object_file__simple(const char *filename)
|
||||
}
|
||||
|
||||
filter_map_fd = find_map_fd(obj, "filters_map");
|
||||
count_map_fd = find_map_fd(obj, "count_map");
|
||||
stats_map_fd = find_map_fd(obj, "stats_map");
|
||||
|
||||
return first_prog_fd;
|
||||
@@ -296,10 +301,14 @@ int main(int argc, char *argv[])
|
||||
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);
|
||||
|
||||
for (uint16_t i = 0; i < conf->filterCount; i++)
|
||||
for (uint16_t i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
if (conf->filters[i].id < 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stdout, "Filter #%" PRIu16 ":\n", (i + 1));
|
||||
|
||||
// Main.
|
||||
@@ -344,6 +353,19 @@ int main(int argc, char *argv[])
|
||||
fprintf(stdout, "ICMP Code => %" PRIu8 "\n", conf->filters[i].icmpopts.code);
|
||||
fprintf(stdout, "ICMP Type => %" PRIu8 "\n", conf->filters[i].icmpopts.type);
|
||||
|
||||
// Payload.
|
||||
if (conf->filters[i].payloadLen > 0)
|
||||
{
|
||||
fprintf(stdout, "\nPayload (%d) => ", conf->filters[i].payloadLen);
|
||||
|
||||
for(uint16_t j = 0; j < conf->filters[i].payloadLen; j++)
|
||||
{
|
||||
fprintf(stdout, "%2hhx ", conf->filters[i].payloadMatch[j]);
|
||||
}
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
fprintf(stdout, "\n\n");
|
||||
}
|
||||
|
||||
@@ -391,13 +413,6 @@ int main(int argc, char *argv[])
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (count_map_fd < 0)
|
||||
{
|
||||
fprintf(stderr, "Error finding 'count_map' BPF map.\n");
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (stats_map_fd < 0)
|
||||
{
|
||||
fprintf(stderr, "Error finding 'stats_map' BPF map.\n");
|
||||
@@ -430,20 +445,17 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Update stats.
|
||||
if ((curTime - statsLastUpdated) > 5)
|
||||
if ((curTime - statsLastUpdated) > 2 && !conf->nostats)
|
||||
{
|
||||
uint16_t key = 0;
|
||||
struct xdpfw_stats *stats;
|
||||
uint32_t key = 0;
|
||||
struct xdpfw_stats stats;
|
||||
|
||||
bpf_map_lookup_elem(stats_map_fd, &key, stats);
|
||||
|
||||
if (stats != NULL)
|
||||
{
|
||||
fprintf(stdout, "\rPackets allowed: %" PRIu64 "\n", stats->allowed);
|
||||
fprintf(stdout, "\rPackets blocked: %" PRIu64 "\n", stats->blocked);
|
||||
bpf_map_lookup_elem(stats_map_fd, &key, &stats);
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
fprintf(stdout, "\rPackets Allowed: %" PRIu64 " | Packets Blocked: %" PRIu64, stats.allowed, stats.blocked);
|
||||
|
||||
statsLastUpdated = time(NULL);
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
@@ -460,6 +472,9 @@ int main(int argc, char *argv[])
|
||||
// Free config.
|
||||
free(conf);
|
||||
|
||||
// Add spacing.
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
// Exit program successfully.
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user