Checkpoint (close to finished).

This commit is contained in:
Christian Deacon
2020-05-06 02:11:38 +00:00
parent f20776cc70
commit 138b3de1cc
4 changed files with 89 additions and 63 deletions

View File

@@ -14,6 +14,7 @@ void SetConfigDefaults(struct config_map *cfg)
{ {
cfg->updateTime = 0; cfg->updateTime = 0;
cfg->interface = "eth0"; cfg->interface = "eth0";
cfg->nostats = 0;
for (uint16_t i = 0; i < MAX_FILTERS; i++) for (uint16_t i = 0; i < MAX_FILTERS; i++)
{ {
@@ -138,6 +139,14 @@ int ReadConfig(struct config_map *cfg)
cfg->updateTime = updateTime; 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. // Read filters in filters_map structure.
setting = config_lookup(&conf, "filters"); setting = config_lookup(&conf, "filters");
@@ -444,9 +453,6 @@ int ReadConfig(struct config_map *cfg)
filters++; filters++;
} }
// Assign filter count to config.
cfg->filterCount = filters;
config_destroy(&conf); config_destroy(&conf);
return 0; return 0;

View File

@@ -7,7 +7,7 @@ struct config_map
{ {
char *interface; char *interface;
uint16_t updateTime; uint16_t updateTime;
uint16_t filterCount; unsigned int nostats : 1;
struct filter filters[MAX_FILTERS]; struct filter filters[MAX_FILTERS];
}; };

View File

@@ -50,14 +50,6 @@ struct bpf_map_def SEC("maps") filters_map =
.max_entries = MAX_FILTERS .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 = struct bpf_map_def SEC("maps") stats_map =
{ {
.type = BPF_MAP_TYPE_ARRAY, .type = BPF_MAP_TYPE_ARRAY,
@@ -69,30 +61,6 @@ struct bpf_map_def SEC("maps") stats_map =
SEC("xdp_prog") SEC("xdp_prog")
int xdp_prog_main(struct xdp_md *ctx) 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. // Initialize data.
void *data_end = (void *)(long)ctx->data_end; void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data; 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++) 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) if (!filter[i] || filter[i]->id < 1)
{ {
break; break;
} }
// Check if the rule is enabled.
if (!filter[i]->enabled) if (!filter[i]->enabled)
{ {
continue; continue;
@@ -241,17 +211,20 @@ int xdp_prog_main(struct xdp_md *ctx)
continue; continue;
} }
// Custom payload. // Payload match.
if (filter[i]->payloadLen > 0) if (filter[i]->payloadLen > 0)
{ {
// Initialize packet data.
uint8_t *pcktData = (data + sizeof(struct ethhdr) + (iph->ihl * 4) + l4headerLen); uint8_t *pcktData = (data + sizeof(struct ethhdr) + (iph->ihl * 4) + l4headerLen);
// Now check packet data and ensure we have enough to match. // 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; continue;
} }
uint8_t found = 1;
for (uint16_t j = 0; j < filter[i]->payloadLen; j++) for (uint16_t j = 0; j < filter[i]->payloadLen; j++)
{ {
if ((*pcktData++) == filter[i]->payloadMatch[j]) if ((*pcktData++) == filter[i]->payloadMatch[j])
@@ -259,8 +232,15 @@ int xdp_prog_main(struct xdp_md *ctx)
continue; continue;
} }
found = 0;
break; break;
} }
if (!found)
{
continue;
}
} }
// Check layer 4 filters. // Check layer 4 filters.
@@ -370,7 +350,32 @@ int xdp_prog_main(struct xdp_md *ctx)
if (matched) 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); bpf_printk("Matched with protocol %" PRIu8 " and sAddr %" PRIu32 "\n", iph->protocol, iph->saddr);
#endif
} }
} }

View File

@@ -34,7 +34,6 @@ const struct option opts[] =
// Other variables. // Other variables.
static uint8_t cont = 1; static uint8_t cont = 1;
static int filter_map_fd = -1; static int filter_map_fd = -1;
static int count_map_fd = -1;
static int stats_map_fd = -1; static int stats_map_fd = -1;
void signalHndl(int tmp) void signalHndl(int tmp)
@@ -87,8 +86,15 @@ void update_BPF(struct config_map *conf)
} }
// Add a filter to the filter maps. // 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) if (bpf_map_update_elem(filter_map_fd, &i, &conf->filters[i], BPF_ANY) == -1)
{ {
fprintf(stderr, "Error updating BPF item #%d\n", i); 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"); 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"); stats_map_fd = find_map_fd(obj, "stats_map");
return first_prog_fd; return first_prog_fd;
@@ -296,10 +301,14 @@ int main(int argc, char *argv[])
fprintf(stdout, "Details:\n"); fprintf(stdout, "Details:\n");
fprintf(stdout, "Interface Name => %s\n", conf->interface); fprintf(stdout, "Interface Name => %s\n", conf->interface);
fprintf(stdout, "Update Time => %" PRIu16 "\n", conf->updateTime); 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)); fprintf(stdout, "Filter #%" PRIu16 ":\n", (i + 1));
// Main. // 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 Code => %" PRIu8 "\n", conf->filters[i].icmpopts.code);
fprintf(stdout, "ICMP Type => %" PRIu8 "\n", conf->filters[i].icmpopts.type); 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"); fprintf(stdout, "\n\n");
} }
@@ -391,13 +413,6 @@ int main(int argc, char *argv[])
return EXIT_FAILURE; 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) if (stats_map_fd < 0)
{ {
fprintf(stderr, "Error finding 'stats_map' BPF map.\n"); fprintf(stderr, "Error finding 'stats_map' BPF map.\n");
@@ -430,20 +445,17 @@ int main(int argc, char *argv[])
} }
// Update stats. // Update stats.
if ((curTime - statsLastUpdated) > 5) if ((curTime - statsLastUpdated) > 2 && !conf->nostats)
{ {
uint16_t key = 0; uint32_t key = 0;
struct xdpfw_stats *stats; struct xdpfw_stats stats;
bpf_map_lookup_elem(stats_map_fd, &key, 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);
fflush(stdout); fflush(stdout);
} fprintf(stdout, "\rPackets Allowed: %" PRIu64 " | Packets Blocked: %" PRIu64, stats.allowed, stats.blocked);
statsLastUpdated = time(NULL);
} }
sleep(1); sleep(1);
@@ -460,6 +472,9 @@ int main(int argc, char *argv[])
// Free config. // Free config.
free(conf); free(conf);
// Add spacing.
fprintf(stdout, "\n");
// Exit program successfully. // Exit program successfully.
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }