Add IPv4 CIDR support and clean up code.
This commit is contained in:
@@ -58,8 +58,8 @@ The following table quickly explains the data types used within the configuratio
|
||||
| enabled | bool | `false` | Whether the rule is enabled or not. |
|
||||
| action | uint | `0` | The value of `0` drops or blocks the packet while `1` allows/passes the packet through. |
|
||||
| block_time | uint | `1` | The amount of seconds to block the source IP for if matched. |
|
||||
| src_ip | string | `NULL` | The source IPv4 address to match (e.g. `10.50.0.3`). |
|
||||
| dst_ip | string | `NULL` | The destination IPv4 address to match (e.g. `10.50.0.4`) |
|
||||
| src_ip | string | `NULL` | The source IPv4 address to match (e.g. `10.50.0.3`). CIDRs are also supported (e.g. `10.50.0.0/24`)! |
|
||||
| dst_ip | string | `NULL` | The destination IPv4 address to match (e.g. `10.50.0.4`). CIDRs are also supported (e.g. `10.50.0.0/24`)! |
|
||||
| src_ip6 | string | `NULL` | The source IPv6 address to match (e.g. `fe80::18c4:dfff:fe70:d8a6`). |
|
||||
| dst_ip6 | string | `NULL` | The destination IPv6 address to match (e.g. `fe80::ac21:14ff:fe4b:3a6d`). |
|
||||
| min_ttl | byte | `NULL` | The minimum TTL (time-to-live) to match. |
|
||||
|
||||
@@ -22,7 +22,7 @@ const struct option opts[] =
|
||||
*
|
||||
* @return Void
|
||||
*/
|
||||
void parsecommandline(struct cmdline *cmd, int argc, char *argv[])
|
||||
void ParseCommandLine(struct cmdline *cmd, int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
|
||||
|
||||
@@ -10,4 +10,4 @@ struct cmdline
|
||||
unsigned int help : 1;
|
||||
};
|
||||
|
||||
void parsecommandline(struct cmdline *cmd, int argc, char *argv[]);
|
||||
void ParseCommandLine(struct cmdline *cmd, int argc, char *argv[]);
|
||||
29
src/config.c
29
src/config.c
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "xdpfw.h"
|
||||
#include "config.h"
|
||||
#include "utils.h"
|
||||
|
||||
FILE *file;
|
||||
|
||||
@@ -18,7 +19,7 @@ FILE *file;
|
||||
*
|
||||
* @return Void
|
||||
*/
|
||||
void setcfgdefaults(struct config *cfg)
|
||||
void SetCfgDefaults(struct config *cfg)
|
||||
{
|
||||
cfg->updatetime = 0;
|
||||
cfg->interface = NULL;
|
||||
@@ -30,13 +31,13 @@ void setcfgdefaults(struct config *cfg)
|
||||
cfg->filters[i].id = 0;
|
||||
cfg->filters[i].enabled = 0;
|
||||
cfg->filters[i].action = 0;
|
||||
cfg->filters[i].srcip = 0;
|
||||
cfg->filters[i].dstip = 0;
|
||||
cfg->filters[i].src_ip = 0;
|
||||
cfg->filters[i].dst_ip = 0;
|
||||
|
||||
for (__u8 j = 0; j < 4; j++)
|
||||
{
|
||||
cfg->filters[i].srcip6[j] = 0;
|
||||
cfg->filters[i].dstip6[j] = 0;
|
||||
cfg->filters[i].src_ip6[j] = 0;
|
||||
cfg->filters[i].dst_ip6[j] = 0;
|
||||
}
|
||||
|
||||
cfg->filters[i].do_min_len = 0;
|
||||
@@ -91,7 +92,7 @@ void setcfgdefaults(struct config *cfg)
|
||||
*
|
||||
* @return 0 on success or 1 on error.
|
||||
*/
|
||||
int opencfg(const char *filename)
|
||||
int OpenCfg(const char *filename)
|
||||
{
|
||||
// Close any existing files.
|
||||
if (file != NULL)
|
||||
@@ -118,7 +119,7 @@ int opencfg(const char *filename)
|
||||
*
|
||||
* @return 0 on success or 1/-1 on error.
|
||||
*/
|
||||
int readcfg(struct config *cfg)
|
||||
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)
|
||||
@@ -232,7 +233,10 @@ int readcfg(struct config *cfg)
|
||||
|
||||
if (config_setting_lookup_string(filter, "src_ip", &sip))
|
||||
{
|
||||
cfg->filters[i].srcip = inet_addr(sip);
|
||||
struct ip ip = ParseIp(sip);
|
||||
|
||||
cfg->filters[i].src_ip = ip.ip;
|
||||
cfg->filters[i].src_cidr = ip.cidr;
|
||||
}
|
||||
|
||||
// Destination IP (not required).
|
||||
@@ -240,7 +244,10 @@ int readcfg(struct config *cfg)
|
||||
|
||||
if (config_setting_lookup_string(filter, "dst_ip", &dip))
|
||||
{
|
||||
cfg->filters[i].dstip = inet_addr(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).
|
||||
@@ -254,7 +261,7 @@ int readcfg(struct config *cfg)
|
||||
|
||||
for (__u8 j = 0; j < 4; j++)
|
||||
{
|
||||
cfg->filters[i].srcip6[j] = in.__in6_u.__u6_addr32[j];
|
||||
cfg->filters[i].src_ip6[j] = in.__in6_u.__u6_addr32[j];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,7 +276,7 @@ int readcfg(struct config *cfg)
|
||||
|
||||
for (__u8 j = 0; j < 4; j++)
|
||||
{
|
||||
cfg->filters[i].dstip6[j] = in.__in6_u.__u6_addr32[j];
|
||||
cfg->filters[i].dst_ip6[j] = in.__in6_u.__u6_addr32[j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,6 @@ struct config
|
||||
struct filter filters[MAX_FILTERS];
|
||||
};
|
||||
|
||||
void setcfgdefaults(struct config *cfg);
|
||||
int opencfg(const char *filename);
|
||||
int readcfg(struct config *cfg);
|
||||
void SetCfgDefaults(struct config *cfg);
|
||||
int OpenCfg(const char *filename);
|
||||
int ReadCfg(struct config *cfg);
|
||||
42
src/utils.h
Normal file
42
src/utils.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct ip
|
||||
{
|
||||
__u32 ip;
|
||||
__u32 cidr;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
17
src/xdp_utils.h
Normal file
17
src/xdp_utils.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "xdpfw.h"
|
||||
|
||||
/**
|
||||
* Checks if an IP is within a specific CIDR range.
|
||||
*
|
||||
* @param src_ip The source/main IP to check against.
|
||||
* @param net_ip The network IP.
|
||||
* @param cidr The CIDR range.
|
||||
*
|
||||
* @return 1 on yes, 0 on no.
|
||||
*/
|
||||
static __always_inline __u8 IsIpInRange(__u32 src_ip, __u32 net_ip, __u8 cidr)
|
||||
{
|
||||
return !((src_ip ^ net_ip) & htonl(0xFFFFFFFFu << (32 - cidr)));
|
||||
}
|
||||
116
src/xdpfw.c
116
src/xdpfw.c
@@ -23,13 +23,14 @@
|
||||
#include "xdpfw.h"
|
||||
#include "config.h"
|
||||
#include "cmdline.h"
|
||||
#include "xdp_utils.h"
|
||||
|
||||
// Other variables.
|
||||
static __u8 cont = 1;
|
||||
static int filtersmap = -1;
|
||||
static int statsmap = -1;
|
||||
|
||||
void signalHndl(int tmp)
|
||||
void SignalHndl(int tmp)
|
||||
{
|
||||
cont = 0;
|
||||
}
|
||||
@@ -41,7 +42,7 @@ void signalHndl(int tmp)
|
||||
*
|
||||
* @return Void
|
||||
*/
|
||||
void updatefilters(struct config *cfg)
|
||||
void UpdateFilters(struct config *cfg)
|
||||
{
|
||||
// Loop through all filters and delete the 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.
|
||||
for (__u8 i = 0; i < MAX_FILTERS; i++)
|
||||
@@ -84,17 +85,17 @@ void updatefilters(struct config *cfg)
|
||||
*
|
||||
* @return 0 on success or -1 on error.
|
||||
*/
|
||||
int updateconfig(struct config *cfg, char *cfgfile)
|
||||
int UpdateConfig(struct config *cfg, char *cfgfile)
|
||||
{
|
||||
// Open config file.
|
||||
if (opencfg(cfgfile) != 0)
|
||||
if (OpenCfg(cfgfile) != 0)
|
||||
{
|
||||
fprintf(stderr, "Error opening filters file: %s\n", cfgfile);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
setcfgdefaults(cfg);
|
||||
SetCfgDefaults(cfg);
|
||||
|
||||
for (__u16 i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
@@ -102,7 +103,7 @@ int updateconfig(struct config *cfg, char *cfgfile)
|
||||
}
|
||||
|
||||
// Read config and check for errors.
|
||||
if (readcfg(cfg) != 0)
|
||||
if (ReadCfg(cfg) != 0)
|
||||
{
|
||||
fprintf(stderr, "Error reading filters file.\n");
|
||||
|
||||
@@ -120,7 +121,7 @@ int updateconfig(struct config *cfg, char *cfgfile)
|
||||
*
|
||||
* @return The map's FD.
|
||||
*/
|
||||
int findmapfd(struct xdp_program *prog, const char *mapname)
|
||||
int FindMapFd(struct xdp_program *prog, const char *mapname)
|
||||
{
|
||||
int fd = -1;
|
||||
|
||||
@@ -155,7 +156,7 @@ int findmapfd(struct xdp_program *prog, const char *mapname)
|
||||
*
|
||||
* @return XDP program structure (pointer) or NULL.
|
||||
*/
|
||||
struct xdp_program *loadbpfobj(const char *filename)
|
||||
struct xdp_program *LoadBpfObj(const char *filename)
|
||||
{
|
||||
struct xdp_program *prog = xdp_program__open_file(filename, "xdp_prog", NULL);
|
||||
|
||||
@@ -178,7 +179,7 @@ struct xdp_program *loadbpfobj(const char *filename)
|
||||
*
|
||||
* @return 0 on success and 1 on error.
|
||||
*/
|
||||
int attachxdp(struct xdp_program *prog, int ifidx, __u8 detach, struct cmdline *cmd)
|
||||
int AttachXdp(struct xdp_program *prog, int ifidx, __u8 detach, struct cmdline *cmd)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -267,6 +268,7 @@ int attachxdp(struct xdp_program *prog, int ifidx, __u8 detach, struct cmdline *
|
||||
}
|
||||
|
||||
struct stat conf_stat;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// Parse the command line.
|
||||
@@ -278,7 +280,7 @@ int main(int argc, char *argv[])
|
||||
.offload = 0
|
||||
};
|
||||
|
||||
parsecommandline(&cmd, argc, argv);
|
||||
ParseCommandLine(&cmd, argc, argv);
|
||||
|
||||
// Check for help menu.
|
||||
if (cmd.help)
|
||||
@@ -314,10 +316,10 @@ int main(int argc, char *argv[])
|
||||
// Initialize config.
|
||||
struct config cfg = {0};
|
||||
|
||||
setcfgdefaults(&cfg);
|
||||
SetCfgDefaults(&cfg);
|
||||
|
||||
// Update config.
|
||||
updateconfig(&cfg, cmd.cfgfile);
|
||||
UpdateConfig(&cfg, cmd.cfgfile);
|
||||
|
||||
// Check for list option.
|
||||
if (cmd.list)
|
||||
@@ -329,7 +331,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
for (uint16_t i = 0; i < MAX_FILTERS; i++)
|
||||
{
|
||||
if (cfg.filters[i].id < 1)
|
||||
struct filter *filter = &cfg.filters[i];
|
||||
|
||||
if (filter->id < 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -337,24 +341,26 @@ int main(int argc, char *argv[])
|
||||
fprintf(stdout, "Filter #%d:\n", (i + 1));
|
||||
|
||||
// Main.
|
||||
fprintf(stdout, "\tID => %d\n", cfg.filters[i].id);
|
||||
fprintf(stdout, "\tEnabled => %d\n", cfg.filters[i].enabled);
|
||||
fprintf(stdout, "\tAction => %d (0 = Block, 1 = Allow).\n\n", cfg.filters[i].action);
|
||||
fprintf(stdout, "\tID => %d\n", filter->id);
|
||||
fprintf(stdout, "\tEnabled => %d\n", filter->enabled);
|
||||
fprintf(stdout, "\tAction => %d (0 = Block, 1 = Allow).\n\n", filter->action);
|
||||
|
||||
// IP Options.
|
||||
fprintf(stdout, "\tIP Options\n");
|
||||
|
||||
// IP addresses require additional code for string printing.
|
||||
struct sockaddr_in sin;
|
||||
sin.sin_addr.s_addr = cfg.filters[i].srcip;
|
||||
sin.sin_addr.s_addr = filter->src_ip;
|
||||
fprintf(stdout, "\t\tSource IPv4 => %s\n", inet_ntoa(sin.sin_addr));
|
||||
fprintf(stdout, "\t\tSource CIDR => %d\n", filter->src_cidr);
|
||||
|
||||
struct sockaddr_in din;
|
||||
din.sin_addr.s_addr = cfg.filters[i].dstip;
|
||||
din.sin_addr.s_addr = filter->dst_ip;
|
||||
fprintf(stdout, "\t\tDestination IPv4 => %s\n", inet_ntoa(din.sin_addr));
|
||||
fprintf(stdout, "\t\tDestination CIDR => %d\n", filter->dst_cidr);
|
||||
|
||||
struct in6_addr sin6;
|
||||
memcpy(&sin6, &cfg.filters[i].srcip6, sizeof(sin6));
|
||||
memcpy(&sin6, &filter->src_ip6, sizeof(sin6));
|
||||
|
||||
char srcipv6[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &sin6, srcipv6, sizeof(srcipv6));
|
||||
@@ -362,7 +368,7 @@ int main(int argc, char *argv[])
|
||||
fprintf(stdout, "\t\tSource IPv6 => %s\n", srcipv6);
|
||||
|
||||
struct in6_addr din6;
|
||||
memcpy(&din6, &cfg.filters[i].dstip6, sizeof(din6));
|
||||
memcpy(&din6, &filter->dst_ip6, sizeof(din6));
|
||||
|
||||
char dstipv6[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &din6, dstipv6, sizeof(dstipv6));
|
||||
@@ -370,40 +376,40 @@ int main(int argc, char *argv[])
|
||||
fprintf(stdout, "\t\tDestination IPv6 => %s\n", dstipv6);
|
||||
|
||||
// Other IP header information.
|
||||
fprintf(stdout, "\t\tMax Length => %d\n", cfg.filters[i].max_len);
|
||||
fprintf(stdout, "\t\tMin Length => %d\n", cfg.filters[i].min_len);
|
||||
fprintf(stdout, "\t\tMax TTL => %d\n", cfg.filters[i].max_ttl);
|
||||
fprintf(stdout, "\t\tMin TTL => %d\n", cfg.filters[i].min_ttl);
|
||||
fprintf(stdout, "\t\tTOS => %d\n", cfg.filters[i].tos);
|
||||
fprintf(stdout, "\t\tPPS => %llu\n", cfg.filters[i].pps);
|
||||
fprintf(stdout, "\t\tBPS => %llu\n", cfg.filters[i].bps);
|
||||
fprintf(stdout, "\t\tBlock Time => %llu\n\n", cfg.filters[i].blocktime);
|
||||
fprintf(stdout, "\t\tMax Length => %d\n", filter->max_len);
|
||||
fprintf(stdout, "\t\tMin Length => %d\n", filter->min_len);
|
||||
fprintf(stdout, "\t\tMax TTL => %d\n", filter->max_ttl);
|
||||
fprintf(stdout, "\t\tMin TTL => %d\n", filter->min_ttl);
|
||||
fprintf(stdout, "\t\tTOS => %d\n", filter->tos);
|
||||
fprintf(stdout, "\t\tPPS => %llu\n", filter->pps);
|
||||
fprintf(stdout, "\t\tBPS => %llu\n", filter->bps);
|
||||
fprintf(stdout, "\t\tBlock Time => %llu\n\n", filter->blocktime);
|
||||
|
||||
// TCP Options.
|
||||
fprintf(stdout, "\tTCP Options\n");
|
||||
fprintf(stdout, "\t\tTCP Enabled => %d\n", cfg.filters[i].tcpopts.enabled);
|
||||
fprintf(stdout, "\t\tTCP Source Port => %d\n", cfg.filters[i].tcpopts.sport);
|
||||
fprintf(stdout, "\t\tTCP Destination Port => %d\n", cfg.filters[i].tcpopts.dport);
|
||||
fprintf(stdout, "\t\tTCP URG Flag => %d\n", cfg.filters[i].tcpopts.urg);
|
||||
fprintf(stdout, "\t\tTCP ACK Flag => %d\n", cfg.filters[i].tcpopts.ack);
|
||||
fprintf(stdout, "\t\tTCP RST Flag => %d\n", cfg.filters[i].tcpopts.rst);
|
||||
fprintf(stdout, "\t\tTCP PSH Flag => %d\n", cfg.filters[i].tcpopts.psh);
|
||||
fprintf(stdout, "\t\tTCP SYN Flag => %d\n", cfg.filters[i].tcpopts.syn);
|
||||
fprintf(stdout, "\t\tTCP FIN Flag => %d\n", cfg.filters[i].tcpopts.fin);
|
||||
fprintf(stdout, "\t\tTCP ECE Flag => %d\n", cfg.filters[i].tcpopts.ece);
|
||||
fprintf(stdout, "\t\tTCP CWR Flag => %d\n\n", cfg.filters[i].tcpopts.cwr);
|
||||
fprintf(stdout, "\t\tTCP Enabled => %d\n", filter->tcpopts.enabled);
|
||||
fprintf(stdout, "\t\tTCP Source Port => %d\n", filter->tcpopts.sport);
|
||||
fprintf(stdout, "\t\tTCP Destination Port => %d\n", filter->tcpopts.dport);
|
||||
fprintf(stdout, "\t\tTCP URG Flag => %d\n", filter->tcpopts.urg);
|
||||
fprintf(stdout, "\t\tTCP ACK Flag => %d\n", filter->tcpopts.ack);
|
||||
fprintf(stdout, "\t\tTCP RST Flag => %d\n", filter->tcpopts.rst);
|
||||
fprintf(stdout, "\t\tTCP PSH Flag => %d\n", filter->tcpopts.psh);
|
||||
fprintf(stdout, "\t\tTCP SYN Flag => %d\n", filter->tcpopts.syn);
|
||||
fprintf(stdout, "\t\tTCP FIN Flag => %d\n", filter->tcpopts.fin);
|
||||
fprintf(stdout, "\t\tTCP ECE Flag => %d\n", filter->tcpopts.ece);
|
||||
fprintf(stdout, "\t\tTCP CWR Flag => %d\n\n", filter->tcpopts.cwr);
|
||||
|
||||
// UDP Options.
|
||||
fprintf(stdout, "\tUDP Options\n");
|
||||
fprintf(stdout, "\t\tUDP Enabled => %d\n", cfg.filters[i].udpopts.enabled);
|
||||
fprintf(stdout, "\t\tUDP Source Port => %d\n", cfg.filters[i].udpopts.sport);
|
||||
fprintf(stdout, "\t\tUDP Destination Port => %d\n\n", cfg.filters[i].udpopts.dport);
|
||||
fprintf(stdout, "\t\tUDP Enabled => %d\n", filter->udpopts.enabled);
|
||||
fprintf(stdout, "\t\tUDP Source Port => %d\n", filter->udpopts.sport);
|
||||
fprintf(stdout, "\t\tUDP Destination Port => %d\n\n", filter->udpopts.dport);
|
||||
|
||||
// ICMP Options.
|
||||
fprintf(stdout, "\tICMP Options\n");
|
||||
fprintf(stdout, "\t\tICMP Enabled => %d\n", cfg.filters[i].icmpopts.enabled);
|
||||
fprintf(stdout, "\t\tICMP Code => %d\n", cfg.filters[i].icmpopts.code);
|
||||
fprintf(stdout, "\t\tICMP Type => %d\n", cfg.filters[i].icmpopts.type);
|
||||
fprintf(stdout, "\t\tICMP Enabled => %d\n", filter->icmpopts.enabled);
|
||||
fprintf(stdout, "\t\tICMP Code => %d\n", filter->icmpopts.code);
|
||||
fprintf(stdout, "\t\tICMP Type => %d\n", filter->icmpopts.type);
|
||||
|
||||
fprintf(stdout, "\n\n");
|
||||
}
|
||||
@@ -425,7 +431,7 @@ int main(int argc, char *argv[])
|
||||
const char *filename = "/etc/xdpfw/xdpfw_kern.o";
|
||||
|
||||
// Load BPF object.
|
||||
struct xdp_program *prog = loadbpfobj(filename);
|
||||
struct xdp_program *prog = LoadBpfObj(filename);
|
||||
|
||||
if (prog == NULL)
|
||||
{
|
||||
@@ -435,14 +441,14 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Attach XDP program.
|
||||
if (attachxdp(prog, ifidx, 0, &cmd))
|
||||
if (AttachXdp(prog, ifidx, 0, &cmd))
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Retrieve BPF maps.
|
||||
filtersmap = findmapfd(prog, "filters_map");
|
||||
statsmap = findmapfd(prog, "stats_map");
|
||||
filtersmap = FindMapFd(prog, "filters_map");
|
||||
statsmap = FindMapFd(prog, "stats_map");
|
||||
|
||||
// Check for valid maps.
|
||||
if (filtersmap < 0)
|
||||
@@ -460,10 +466,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Update BPF maps.
|
||||
updatefilters(&cfg);
|
||||
UpdateFilters(&cfg);
|
||||
|
||||
// Signal.
|
||||
signal(SIGINT, signalHndl);
|
||||
signal(SIGINT, SignalHndl);
|
||||
|
||||
// Receive CPU count for stats map parsing.
|
||||
int cpus = get_nprocs_conf();
|
||||
@@ -492,15 +498,15 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
// Check if config file have been modified
|
||||
if (stat(cmd.cfgfile, &conf_stat) == 0 && conf_stat.st_mtime > lastupdated) {
|
||||
// Memleak fix for strdup() in updateconfig()
|
||||
// Memleak fix for strdup() in UpdateConfig()
|
||||
// Before updating it again, we need to free the old return value
|
||||
free(cfg.interface);
|
||||
|
||||
// Update config.
|
||||
updateconfig(&cfg, cmd.cfgfile);
|
||||
UpdateConfig(&cfg, cmd.cfgfile);
|
||||
|
||||
// Update BPF maps.
|
||||
updatefilters(&cfg);
|
||||
UpdateFilters(&cfg);
|
||||
|
||||
// Update timer
|
||||
lastupdated = time(NULL);
|
||||
@@ -553,7 +559,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Detach XDP program.
|
||||
attachxdp(prog, ifidx, 1, &cmd);
|
||||
AttachXdp(prog, ifidx, 1, &cmd);
|
||||
|
||||
// Add spacing.
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
11
src/xdpfw.h
11
src/xdpfw.h
@@ -101,11 +101,14 @@ struct filter
|
||||
|
||||
__u8 action;
|
||||
|
||||
__u32 srcip;
|
||||
__u32 dstip;
|
||||
__u32 src_ip;
|
||||
__u8 src_cidr;
|
||||
|
||||
__u32 srcip6[4];
|
||||
__u32 dstip6[4];
|
||||
__u32 dst_ip;
|
||||
__u8 dst_cidr;
|
||||
|
||||
__u32 src_ip6[4];
|
||||
__u32 dst_ip6[4];
|
||||
|
||||
unsigned int do_min_ttl : 1;
|
||||
__u8 min_ttl;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <xdp/prog_dispatcher.h>
|
||||
|
||||
#include "xdpfw.h"
|
||||
#include "xdp_utils.h"
|
||||
|
||||
#ifndef memcpy
|
||||
#define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n))
|
||||
@@ -103,7 +104,7 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
// Initialize IP headers.
|
||||
struct iphdr *iph = NULL;
|
||||
struct ipv6hdr *iph6 = NULL;
|
||||
__u128 srcip6 = 0;
|
||||
__u128 src_ip6 = 0;
|
||||
|
||||
// Set IPv4 and IPv6 common variables.
|
||||
if (eth->h_proto == htons(ETH_P_IPV6))
|
||||
@@ -115,7 +116,7 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
return XDP_DROP;
|
||||
}
|
||||
|
||||
memcpy(&srcip6, &iph6->saddr.in6_u.u6_addr32, sizeof(srcip6));
|
||||
memcpy(&src_ip6, &iph6->saddr.in6_u.u6_addr32, sizeof(src_ip6));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -144,7 +145,7 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
|
||||
if (iph6)
|
||||
{
|
||||
blocked = bpf_map_lookup_elem(&ip6_blacklist_map, &srcip6);
|
||||
blocked = bpf_map_lookup_elem(&ip6_blacklist_map, &src_ip6);
|
||||
}
|
||||
else if (iph)
|
||||
{
|
||||
@@ -162,7 +163,7 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
// Remove element from map.
|
||||
if (iph6)
|
||||
{
|
||||
bpf_map_delete_elem(&ip6_blacklist_map, &srcip6);
|
||||
bpf_map_delete_elem(&ip6_blacklist_map, &src_ip6);
|
||||
}
|
||||
else if (iph)
|
||||
{
|
||||
@@ -192,7 +193,7 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
|
||||
if (iph6)
|
||||
{
|
||||
ip_stats = bpf_map_lookup_elem(&ip6_stats_map, &srcip6);
|
||||
ip_stats = bpf_map_lookup_elem(&ip6_stats_map, &src_ip6);
|
||||
}
|
||||
else if (iph)
|
||||
{
|
||||
@@ -234,7 +235,7 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
|
||||
if (iph6)
|
||||
{
|
||||
bpf_map_update_elem(&ip6_stats_map, &srcip6, &new, BPF_ANY);
|
||||
bpf_map_update_elem(&ip6_stats_map, &src_ip6, &new, BPF_ANY);
|
||||
}
|
||||
else if (iph)
|
||||
{
|
||||
@@ -353,19 +354,19 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
if (iph6)
|
||||
{
|
||||
// Source address.
|
||||
if (filter->srcip6[0] != 0 && (iph6->saddr.in6_u.u6_addr32[0] != filter->srcip6[0] || iph6->saddr.in6_u.u6_addr32[1] != filter->srcip6[1] || iph6->saddr.in6_u.u6_addr32[2] != filter->srcip6[2] || iph6->saddr.in6_u.u6_addr32[3] != filter->srcip6[3]))
|
||||
if (filter->src_ip6[0] != 0 && (iph6->saddr.in6_u.u6_addr32[0] != filter->src_ip6[0] || iph6->saddr.in6_u.u6_addr32[1] != filter->src_ip6[1] || iph6->saddr.in6_u.u6_addr32[2] != filter->src_ip6[2] || iph6->saddr.in6_u.u6_addr32[3] != filter->src_ip6[3]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Destination address.
|
||||
if (filter->dstip6[0] != 0 && (iph6->daddr.in6_u.u6_addr32[0] != filter->dstip6[0] || iph6->daddr.in6_u.u6_addr32[1] != filter->dstip6[1] || iph6->daddr.in6_u.u6_addr32[2] != filter->dstip6[2] || iph6->daddr.in6_u.u6_addr32[3] != filter->dstip6[3]))
|
||||
if (filter->dst_ip6[0] != 0 && (iph6->daddr.in6_u.u6_addr32[0] != filter->dst_ip6[0] || iph6->daddr.in6_u.u6_addr32[1] != filter->dst_ip6[1] || iph6->daddr.in6_u.u6_addr32[2] != filter->dst_ip6[2] || iph6->daddr.in6_u.u6_addr32[3] != filter->dst_ip6[3]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef ALLOWSINGLEIPV4V6
|
||||
if (filter->srcip != 0 || filter->dstip != 0)
|
||||
if (filter->src_ip != 0 || filter->dst_ip != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -398,19 +399,35 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
else if (iph)
|
||||
{
|
||||
// Source address.
|
||||
if (filter->srcip && iph->saddr != filter->srcip)
|
||||
if (filter->src_ip)
|
||||
{
|
||||
continue;
|
||||
if (filter->src_cidr == 32 && iph->saddr != filter->src_ip)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IsIpInRange(iph->saddr, filter->src_ip, filter->src_cidr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Destination address.
|
||||
if (filter->dstip != 0 && iph->daddr != filter->dstip)
|
||||
if (filter->dst_ip)
|
||||
{
|
||||
continue;
|
||||
if (filter->dst_cidr == 32 && iph->daddr != filter->dst_ip)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IsIpInRange(iph->daddr, filter->dst_ip, filter->dst_cidr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ALLOWSINGLEIPV4V6
|
||||
if ((filter->srcip6[0] != 0 || filter->srcip6[1] != 0 || filter->srcip6[2] != 0 || filter->srcip6[3] != 0) || (filter->dstip6[0] != 0 || filter->dstip6[1] != 0 || filter->dstip6[2] != 0 || filter->dstip6[3] != 0))
|
||||
if ((filter->src_ip6[0] != 0 || filter->src_ip6[1] != 0 || filter->src_ip6[2] != 0 || filter->src_ip6[3] != 0) || (filter->dst_ip6[0] != 0 || filter->dst_ip6[1] != 0 || filter->dst_ip6[2] != 0 || filter->dst_ip6[3] != 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -615,7 +632,7 @@ int xdp_prog_main(struct xdp_md *ctx)
|
||||
|
||||
if (iph6)
|
||||
{
|
||||
bpf_map_update_elem(&ip6_blacklist_map, &srcip6, &newTime, BPF_ANY);
|
||||
bpf_map_update_elem(&ip6_blacklist_map, &src_ip6, &newTime, BPF_ANY);
|
||||
}
|
||||
else if (iph)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user