Add IPv4 CIDR support and clean up code.

This commit is contained in:
Christian Deacon
2024-08-13 02:55:01 -04:00
parent 1ce17ddd77
commit 91138f1116
10 changed files with 184 additions and 92 deletions

View File

@@ -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. | | 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. | | 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. | | 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`). | | 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`) | | 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`). | | 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`). | | 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. | | min_ttl | byte | `NULL` | The minimum TTL (time-to-live) to match. |

View File

@@ -22,7 +22,7 @@ const struct option opts[] =
* *
* @return Void * @return Void
*/ */
void parsecommandline(struct cmdline *cmd, int argc, char *argv[]) void ParseCommandLine(struct cmdline *cmd, int argc, char *argv[])
{ {
int c; int c;

View File

@@ -10,4 +10,4 @@ struct cmdline
unsigned int help : 1; unsigned int help : 1;
}; };
void parsecommandline(struct cmdline *cmd, int argc, char *argv[]); void ParseCommandLine(struct cmdline *cmd, int argc, char *argv[]);

View File

@@ -8,6 +8,7 @@
#include "xdpfw.h" #include "xdpfw.h"
#include "config.h" #include "config.h"
#include "utils.h"
FILE *file; FILE *file;
@@ -18,7 +19,7 @@ FILE *file;
* *
* @return Void * @return Void
*/ */
void setcfgdefaults(struct config *cfg) void SetCfgDefaults(struct config *cfg)
{ {
cfg->updatetime = 0; cfg->updatetime = 0;
cfg->interface = NULL; cfg->interface = NULL;
@@ -30,13 +31,13 @@ void setcfgdefaults(struct config *cfg)
cfg->filters[i].id = 0; cfg->filters[i].id = 0;
cfg->filters[i].enabled = 0; cfg->filters[i].enabled = 0;
cfg->filters[i].action = 0; cfg->filters[i].action = 0;
cfg->filters[i].srcip = 0; cfg->filters[i].src_ip = 0;
cfg->filters[i].dstip = 0; cfg->filters[i].dst_ip = 0;
for (__u8 j = 0; j < 4; j++) for (__u8 j = 0; j < 4; j++)
{ {
cfg->filters[i].srcip6[j] = 0; cfg->filters[i].src_ip6[j] = 0;
cfg->filters[i].dstip6[j] = 0; cfg->filters[i].dst_ip6[j] = 0;
} }
cfg->filters[i].do_min_len = 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. * @return 0 on success or 1 on error.
*/ */
int opencfg(const char *filename) int OpenCfg(const char *filename)
{ {
// Close any existing files. // Close any existing files.
if (file != NULL) if (file != NULL)
@@ -118,7 +119,7 @@ int opencfg(const char *filename)
* *
* @return 0 on success or 1/-1 on error. * @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. // Not sure why this would be set to NULL after checking for it in OpenConfig(), but just for safety.
if (file == NULL) if (file == NULL)
@@ -232,7 +233,10 @@ int readcfg(struct config *cfg)
if (config_setting_lookup_string(filter, "src_ip", &sip)) 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). // Destination IP (not required).
@@ -240,7 +244,10 @@ int readcfg(struct config *cfg)
if (config_setting_lookup_string(filter, "dst_ip", &dip)) 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). // Source IP (IPv6) (not required).
@@ -254,7 +261,7 @@ int readcfg(struct config *cfg)
for (__u8 j = 0; j < 4; j++) 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++) 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];
} }
} }

View File

@@ -13,6 +13,6 @@ struct config
struct filter filters[MAX_FILTERS]; struct filter filters[MAX_FILTERS];
}; };
void setcfgdefaults(struct config *cfg); void SetCfgDefaults(struct config *cfg);
int opencfg(const char *filename); int OpenCfg(const char *filename);
int readcfg(struct config *cfg); int ReadCfg(struct config *cfg);

42
src/utils.h Normal file
View 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
View 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)));
}

View File

@@ -23,13 +23,14 @@
#include "xdpfw.h" #include "xdpfw.h"
#include "config.h" #include "config.h"
#include "cmdline.h" #include "cmdline.h"
#include "xdp_utils.h"
// Other variables. // Other variables.
static __u8 cont = 1; static __u8 cont = 1;
static int filtersmap = -1; static int filtersmap = -1;
static int statsmap = -1; static int statsmap = -1;
void signalHndl(int tmp) void SignalHndl(int tmp)
{ {
cont = 0; cont = 0;
} }
@@ -41,7 +42,7 @@ void signalHndl(int tmp)
* *
* @return Void * @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. // 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++) 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. * @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. // Open config file.
if (opencfg(cfgfile) != 0) if (OpenCfg(cfgfile) != 0)
{ {
fprintf(stderr, "Error opening filters file: %s\n", cfgfile); fprintf(stderr, "Error opening filters file: %s\n", cfgfile);
return -1; return -1;
} }
setcfgdefaults(cfg); SetCfgDefaults(cfg);
for (__u16 i = 0; i < MAX_FILTERS; i++) 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. // Read config and check for errors.
if (readcfg(cfg) != 0) if (ReadCfg(cfg) != 0)
{ {
fprintf(stderr, "Error reading filters file.\n"); fprintf(stderr, "Error reading filters file.\n");
@@ -120,7 +121,7 @@ int updateconfig(struct config *cfg, char *cfgfile)
* *
* @return The map's FD. * @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; int fd = -1;
@@ -155,7 +156,7 @@ int findmapfd(struct xdp_program *prog, const char *mapname)
* *
* @return XDP program structure (pointer) or NULL. * @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); 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. * @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; int err;
@@ -267,6 +268,7 @@ int attachxdp(struct xdp_program *prog, int ifidx, __u8 detach, struct cmdline *
} }
struct stat conf_stat; struct stat conf_stat;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// Parse the command line. // Parse the command line.
@@ -278,7 +280,7 @@ int main(int argc, char *argv[])
.offload = 0 .offload = 0
}; };
parsecommandline(&cmd, argc, argv); ParseCommandLine(&cmd, argc, argv);
// Check for help menu. // Check for help menu.
if (cmd.help) if (cmd.help)
@@ -314,10 +316,10 @@ int main(int argc, char *argv[])
// Initialize config. // Initialize config.
struct config cfg = {0}; struct config cfg = {0};
setcfgdefaults(&cfg); SetCfgDefaults(&cfg);
// Update config. // Update config.
updateconfig(&cfg, cmd.cfgfile); UpdateConfig(&cfg, cmd.cfgfile);
// Check for list option. // Check for list option.
if (cmd.list) if (cmd.list)
@@ -329,7 +331,9 @@ int main(int argc, char *argv[])
for (uint16_t i = 0; i < MAX_FILTERS; i++) 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; break;
} }
@@ -337,24 +341,26 @@ int main(int argc, char *argv[])
fprintf(stdout, "Filter #%d:\n", (i + 1)); fprintf(stdout, "Filter #%d:\n", (i + 1));
// Main. // Main.
fprintf(stdout, "\tID => %d\n", cfg.filters[i].id); fprintf(stdout, "\tID => %d\n", filter->id);
fprintf(stdout, "\tEnabled => %d\n", cfg.filters[i].enabled); fprintf(stdout, "\tEnabled => %d\n", filter->enabled);
fprintf(stdout, "\tAction => %d (0 = Block, 1 = Allow).\n\n", cfg.filters[i].action); fprintf(stdout, "\tAction => %d (0 = Block, 1 = Allow).\n\n", filter->action);
// IP Options. // IP Options.
fprintf(stdout, "\tIP Options\n"); fprintf(stdout, "\tIP Options\n");
// IP addresses require additional code for string printing. // IP addresses require additional code for string printing.
struct sockaddr_in sin; 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 IPv4 => %s\n", inet_ntoa(sin.sin_addr));
fprintf(stdout, "\t\tSource CIDR => %d\n", filter->src_cidr);
struct sockaddr_in din; 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 IPv4 => %s\n", inet_ntoa(din.sin_addr));
fprintf(stdout, "\t\tDestination CIDR => %d\n", filter->dst_cidr);
struct in6_addr sin6; struct in6_addr sin6;
memcpy(&sin6, &cfg.filters[i].srcip6, sizeof(sin6)); memcpy(&sin6, &filter->src_ip6, sizeof(sin6));
char srcipv6[INET6_ADDRSTRLEN]; char srcipv6[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &sin6, srcipv6, sizeof(srcipv6)); 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); fprintf(stdout, "\t\tSource IPv6 => %s\n", srcipv6);
struct in6_addr din6; struct in6_addr din6;
memcpy(&din6, &cfg.filters[i].dstip6, sizeof(din6)); memcpy(&din6, &filter->dst_ip6, sizeof(din6));
char dstipv6[INET6_ADDRSTRLEN]; char dstipv6[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &din6, dstipv6, sizeof(dstipv6)); 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); fprintf(stdout, "\t\tDestination IPv6 => %s\n", dstipv6);
// Other IP header information. // Other IP header information.
fprintf(stdout, "\t\tMax Length => %d\n", cfg.filters[i].max_len); fprintf(stdout, "\t\tMax Length => %d\n", filter->max_len);
fprintf(stdout, "\t\tMin Length => %d\n", cfg.filters[i].min_len); fprintf(stdout, "\t\tMin Length => %d\n", filter->min_len);
fprintf(stdout, "\t\tMax TTL => %d\n", cfg.filters[i].max_ttl); fprintf(stdout, "\t\tMax TTL => %d\n", filter->max_ttl);
fprintf(stdout, "\t\tMin TTL => %d\n", cfg.filters[i].min_ttl); fprintf(stdout, "\t\tMin TTL => %d\n", filter->min_ttl);
fprintf(stdout, "\t\tTOS => %d\n", cfg.filters[i].tos); fprintf(stdout, "\t\tTOS => %d\n", filter->tos);
fprintf(stdout, "\t\tPPS => %llu\n", cfg.filters[i].pps); fprintf(stdout, "\t\tPPS => %llu\n", filter->pps);
fprintf(stdout, "\t\tBPS => %llu\n", cfg.filters[i].bps); fprintf(stdout, "\t\tBPS => %llu\n", filter->bps);
fprintf(stdout, "\t\tBlock Time => %llu\n\n", cfg.filters[i].blocktime); fprintf(stdout, "\t\tBlock Time => %llu\n\n", filter->blocktime);
// TCP Options. // TCP Options.
fprintf(stdout, "\tTCP Options\n"); fprintf(stdout, "\tTCP Options\n");
fprintf(stdout, "\t\tTCP Enabled => %d\n", cfg.filters[i].tcpopts.enabled); fprintf(stdout, "\t\tTCP Enabled => %d\n", filter->tcpopts.enabled);
fprintf(stdout, "\t\tTCP Source Port => %d\n", cfg.filters[i].tcpopts.sport); fprintf(stdout, "\t\tTCP Source Port => %d\n", filter->tcpopts.sport);
fprintf(stdout, "\t\tTCP Destination Port => %d\n", cfg.filters[i].tcpopts.dport); fprintf(stdout, "\t\tTCP Destination Port => %d\n", filter->tcpopts.dport);
fprintf(stdout, "\t\tTCP URG Flag => %d\n", cfg.filters[i].tcpopts.urg); fprintf(stdout, "\t\tTCP URG Flag => %d\n", filter->tcpopts.urg);
fprintf(stdout, "\t\tTCP ACK Flag => %d\n", cfg.filters[i].tcpopts.ack); fprintf(stdout, "\t\tTCP ACK Flag => %d\n", filter->tcpopts.ack);
fprintf(stdout, "\t\tTCP RST Flag => %d\n", cfg.filters[i].tcpopts.rst); fprintf(stdout, "\t\tTCP RST Flag => %d\n", filter->tcpopts.rst);
fprintf(stdout, "\t\tTCP PSH Flag => %d\n", cfg.filters[i].tcpopts.psh); fprintf(stdout, "\t\tTCP PSH Flag => %d\n", filter->tcpopts.psh);
fprintf(stdout, "\t\tTCP SYN Flag => %d\n", cfg.filters[i].tcpopts.syn); fprintf(stdout, "\t\tTCP SYN Flag => %d\n", filter->tcpopts.syn);
fprintf(stdout, "\t\tTCP FIN Flag => %d\n", cfg.filters[i].tcpopts.fin); fprintf(stdout, "\t\tTCP FIN Flag => %d\n", filter->tcpopts.fin);
fprintf(stdout, "\t\tTCP ECE Flag => %d\n", cfg.filters[i].tcpopts.ece); fprintf(stdout, "\t\tTCP ECE Flag => %d\n", filter->tcpopts.ece);
fprintf(stdout, "\t\tTCP CWR Flag => %d\n\n", cfg.filters[i].tcpopts.cwr); fprintf(stdout, "\t\tTCP CWR Flag => %d\n\n", filter->tcpopts.cwr);
// UDP Options. // UDP Options.
fprintf(stdout, "\tUDP Options\n"); fprintf(stdout, "\tUDP Options\n");
fprintf(stdout, "\t\tUDP Enabled => %d\n", cfg.filters[i].udpopts.enabled); fprintf(stdout, "\t\tUDP Enabled => %d\n", filter->udpopts.enabled);
fprintf(stdout, "\t\tUDP Source Port => %d\n", cfg.filters[i].udpopts.sport); fprintf(stdout, "\t\tUDP Source Port => %d\n", filter->udpopts.sport);
fprintf(stdout, "\t\tUDP Destination Port => %d\n\n", cfg.filters[i].udpopts.dport); fprintf(stdout, "\t\tUDP Destination Port => %d\n\n", filter->udpopts.dport);
// ICMP Options. // ICMP Options.
fprintf(stdout, "\tICMP Options\n"); fprintf(stdout, "\tICMP Options\n");
fprintf(stdout, "\t\tICMP Enabled => %d\n", cfg.filters[i].icmpopts.enabled); fprintf(stdout, "\t\tICMP Enabled => %d\n", filter->icmpopts.enabled);
fprintf(stdout, "\t\tICMP Code => %d\n", cfg.filters[i].icmpopts.code); fprintf(stdout, "\t\tICMP Code => %d\n", filter->icmpopts.code);
fprintf(stdout, "\t\tICMP Type => %d\n", cfg.filters[i].icmpopts.type); fprintf(stdout, "\t\tICMP Type => %d\n", filter->icmpopts.type);
fprintf(stdout, "\n\n"); fprintf(stdout, "\n\n");
} }
@@ -425,7 +431,7 @@ int main(int argc, char *argv[])
const char *filename = "/etc/xdpfw/xdpfw_kern.o"; const char *filename = "/etc/xdpfw/xdpfw_kern.o";
// Load BPF object. // Load BPF object.
struct xdp_program *prog = loadbpfobj(filename); struct xdp_program *prog = LoadBpfObj(filename);
if (prog == NULL) if (prog == NULL)
{ {
@@ -435,14 +441,14 @@ int main(int argc, char *argv[])
} }
// Attach XDP program. // Attach XDP program.
if (attachxdp(prog, ifidx, 0, &cmd)) if (AttachXdp(prog, ifidx, 0, &cmd))
{ {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Retrieve BPF maps. // Retrieve BPF maps.
filtersmap = findmapfd(prog, "filters_map"); filtersmap = FindMapFd(prog, "filters_map");
statsmap = findmapfd(prog, "stats_map"); statsmap = FindMapFd(prog, "stats_map");
// Check for valid maps. // Check for valid maps.
if (filtersmap < 0) if (filtersmap < 0)
@@ -460,10 +466,10 @@ int main(int argc, char *argv[])
} }
// Update BPF maps. // Update BPF maps.
updatefilters(&cfg); UpdateFilters(&cfg);
// Signal. // Signal.
signal(SIGINT, signalHndl); signal(SIGINT, SignalHndl);
// Receive CPU count for stats map parsing. // Receive CPU count for stats map parsing.
int cpus = get_nprocs_conf(); int cpus = get_nprocs_conf();
@@ -492,15 +498,15 @@ int main(int argc, char *argv[])
{ {
// Check if config file have been modified // Check if config file have been modified
if (stat(cmd.cfgfile, &conf_stat) == 0 && conf_stat.st_mtime > lastupdated) { 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 // Before updating it again, we need to free the old return value
free(cfg.interface); free(cfg.interface);
// Update config. // Update config.
updateconfig(&cfg, cmd.cfgfile); UpdateConfig(&cfg, cmd.cfgfile);
// Update BPF maps. // Update BPF maps.
updatefilters(&cfg); UpdateFilters(&cfg);
// Update timer // Update timer
lastupdated = time(NULL); lastupdated = time(NULL);
@@ -553,7 +559,7 @@ int main(int argc, char *argv[])
} }
// Detach XDP program. // Detach XDP program.
attachxdp(prog, ifidx, 1, &cmd); AttachXdp(prog, ifidx, 1, &cmd);
// Add spacing. // Add spacing.
fprintf(stdout, "\n"); fprintf(stdout, "\n");

View File

@@ -101,11 +101,14 @@ struct filter
__u8 action; __u8 action;
__u32 srcip; __u32 src_ip;
__u32 dstip; __u8 src_cidr;
__u32 srcip6[4]; __u32 dst_ip;
__u32 dstip6[4]; __u8 dst_cidr;
__u32 src_ip6[4];
__u32 dst_ip6[4];
unsigned int do_min_ttl : 1; unsigned int do_min_ttl : 1;
__u8 min_ttl; __u8 min_ttl;

View File

@@ -16,6 +16,7 @@
#include <xdp/prog_dispatcher.h> #include <xdp/prog_dispatcher.h>
#include "xdpfw.h" #include "xdpfw.h"
#include "xdp_utils.h"
#ifndef memcpy #ifndef memcpy
#define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n)) #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. // Initialize IP headers.
struct iphdr *iph = NULL; struct iphdr *iph = NULL;
struct ipv6hdr *iph6 = NULL; struct ipv6hdr *iph6 = NULL;
__u128 srcip6 = 0; __u128 src_ip6 = 0;
// Set IPv4 and IPv6 common variables. // Set IPv4 and IPv6 common variables.
if (eth->h_proto == htons(ETH_P_IPV6)) if (eth->h_proto == htons(ETH_P_IPV6))
@@ -115,7 +116,7 @@ int xdp_prog_main(struct xdp_md *ctx)
return XDP_DROP; 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 else
{ {
@@ -144,7 +145,7 @@ int xdp_prog_main(struct xdp_md *ctx)
if (iph6) if (iph6)
{ {
blocked = bpf_map_lookup_elem(&ip6_blacklist_map, &srcip6); blocked = bpf_map_lookup_elem(&ip6_blacklist_map, &src_ip6);
} }
else if (iph) else if (iph)
{ {
@@ -162,7 +163,7 @@ int xdp_prog_main(struct xdp_md *ctx)
// Remove element from map. // Remove element from map.
if (iph6) if (iph6)
{ {
bpf_map_delete_elem(&ip6_blacklist_map, &srcip6); bpf_map_delete_elem(&ip6_blacklist_map, &src_ip6);
} }
else if (iph) else if (iph)
{ {
@@ -192,7 +193,7 @@ int xdp_prog_main(struct xdp_md *ctx)
if (iph6) 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) else if (iph)
{ {
@@ -234,7 +235,7 @@ int xdp_prog_main(struct xdp_md *ctx)
if (iph6) 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) else if (iph)
{ {
@@ -353,19 +354,19 @@ int xdp_prog_main(struct xdp_md *ctx)
if (iph6) if (iph6)
{ {
// Source address. // 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; continue;
} }
// Destination address. // 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; continue;
} }
#ifdef ALLOWSINGLEIPV4V6 #ifdef ALLOWSINGLEIPV4V6
if (filter->srcip != 0 || filter->dstip != 0) if (filter->src_ip != 0 || filter->dst_ip != 0)
{ {
continue; continue;
} }
@@ -398,19 +399,35 @@ int xdp_prog_main(struct xdp_md *ctx)
else if (iph) else if (iph)
{ {
// Source address. // 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. // 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 #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; continue;
} }
@@ -615,7 +632,7 @@ int xdp_prog_main(struct xdp_md *ctx)
if (iph6) 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) else if (iph)
{ {