more files

This commit is contained in:
Daniel Brahneborg 2025-12-04 15:52:13 +01:00
parent b62e2706f6
commit 048bf96e51
6 changed files with 377 additions and 0 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@ CMakeCache.txt
CMakeFiles
cmake_install.cmake
.DS_Store
Makefile

9
CMakeLists.txt Normal file
View file

@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.10)
project(AutoFW)
add_executable(autofw
autofw.c
)

342
autofw.c Normal file
View file

@ -0,0 +1,342 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "matcher.h"
#include "vbuf.h"
static void
fclose_ptr(FILE** p)
{
if (!p || !*p)
return;
fclose(*p);
*p = NULL;
}
typedef struct {
bool obsolete;
uint32_t ip;
uint8_t width;
} iprange_t;
static pbuf_t black_ranges;
static pbuf_t white_ranges;
static pbuf_t new_ranges;
static pbuf_t new_b_ranges;
static iprange_t*
iprange_create(uint32_t ip, uint8_t width)
{
iprange_t* const range = malloc(sizeof(*range));
*range = (iprange_t) {
.ip = ip & ~0U << (32 - width),
.width = width,
};
return range;
}
static void
iprange_add(const char* ipstr, uint8_t width, bool white)
{
struct in_addr addr;
int const rc = inet_pton(AF_INET, ipstr, &addr);
if (!rc) return;
#if 0
printf("%s: inet_pton `%s' => %d.%d.%d.%d\n",
__FUNCTION__,
ipstr,
addr.s_addr >> 24,
(addr.s_addr >> 16) & 0xff,
(addr.s_addr >> 8) & 0xff,
(addr.s_addr >> 0) & 0xff);
#endif
iprange_t* const range = iprange_create(ntohl(addr.s_addr), width);
pbuf_append(white ? &white_ranges : &black_ranges, range);
}
static void
iprange_load(const char* filename, bool white)
{
FILE* __attribute__((cleanup(fclose_ptr))) fp = fopen(filename, "r");
if (!fp)
return;
regexp_matcher_t __attribute__((cleanup(matcher_destroy))) matcher;
matcher_init_regexp(&matcher,
"([0-9\\.]+)" // ipv4
"("
"/([0-9]+)" // optional width
")?");
vbuf_t __attribute__((cleanup(vbuf_freeptr))) vbuf;
vbuf_init0(&vbuf);
int len;
while ((len = vbuf_gets(&vbuf, fp)) > -1) {
char* const line = vbuf_tostring(&vbuf);
int rc = matcher_match(&matcher, line);
// printf("matcher on `%s' returned %d\n", line, rc);
if (rc < 2)
continue;
switch (rc) {
case 2:
iprange_add(matcher_result(&matcher, 1), 32, white);
break;
case 4:
iprange_add(
matcher_result(&matcher, 1),
atoi(matcher_result(&matcher, 3)),
white);
break;
}
}
}
static int
iprange_cmp(const void* a, const void* b)
{
const iprange_t* const r_a = *((iprange_t**)a);
const iprange_t* const r_b = *((iprange_t**)b);
if (r_a->ip < r_b->ip)
return -1;
if (r_a->ip > r_b->ip)
return 1;
return 0;
}
static void
iprange_join(iprange_t* prev, iprange_t* curr)
{
uint32_t const prev_mask = ~0U << (32 - prev->width);
#if 0
uint32_t const curr_mask = ~0U << (32 - curr->width);
printf("masks: prev 0x%08x curr 0x%08x\n", prev_mask, curr_mask);
printf("masked: prev 0x%08x curr 0x%08x\n", prev->ip & prev_mask, curr->ip & curr_mask);
#endif
if ((prev->ip & prev_mask) == (curr->ip & prev_mask)) {
curr->obsolete = true;
return;
}
int min_width = prev->width < curr->width ? prev->width : curr->width;
if (min_width < 8)
min_width = 8;
int const max_width = prev->width > curr->width ? prev->width : curr->width;
// printf("widths: min %d max %d\n", min_width, max_width);
if (max_width - min_width > 8) {
// printf("width difference %d, too much\n", max_width - min_width);
return;
}
int new_width = max_width;
uint32_t new_mask = 0;
for (;;) {
if ((new_width <= 8) || (max_width - new_width > 8)) {
// printf("nothing in common with at least 8 bits\n");
return;
}
new_width = new_width - 1;
new_mask = ~0U << (32 - new_width);
uint32_t const prev_masked = prev->ip & new_mask;
uint32_t const curr_masked = curr->ip & new_mask;
#if 0
printf("new masked with width %d: prev 0x%08x curr 0x%08x\n",
new_width, prev_masked, curr_masked);
#endif
if (prev_masked == curr_masked)
break;
if (!(new_width & 7)) {
// printf("too far apart, giving up\n");
return;
}
}
uint32_t const new_ip = prev->ip & new_mask;
iprange_t* const range = iprange_create(new_ip, new_width);
pbuf_append(&new_ranges, range);
prev->obsolete = true;
curr->obsolete = true;
}
static void
ipranges_merge(void)
{
iprange_t* prev = NULL;
iprange_t* curr;
PBUF_FOREACH(curr, &black_ranges)
if (!prev) {
prev = curr;
continue;
}
#if 0
printf("comparing %d.%d.%d.%d/%d and %d.%d.%d.%d/%d\n",
prev->ip >> 24,
(prev->ip >> 16) & 0xff,
(prev->ip >> 8) & 0xff,
(prev->ip >> 0) & 0xff,
prev->width,
curr->ip >> 24,
(curr->ip >> 16) & 0xff,
(curr->ip >> 8) & 0xff,
(curr->ip >> 0) & 0xff,
curr->width);
#endif
iprange_join(prev, curr);
if (!curr->obsolete)
prev = curr;
PBUF_FOREACH_END
}
static void
iprange_maybe_add_b_block(uint32_t counter, uint32_t last_block)
{
if (counter < 4)
return;
#if 0
printf("found %d ips in block %d.%d.0.0/16\n",
counter,
last_block >> 24,
(last_block >> 16) & 0xff);
#endif
iprange_t* const range = iprange_create(last_block, 16);
pbuf_append(&new_b_ranges, range);
}
static int
iprange_match_block(void* obj, const void* arg)
{
iprange_t* const block = obj;
const iprange_t* const curr = arg;
if (curr->width < block->width)
return 0;
uint32_t const block_mask = ~0U << (32 - block->width);
if ((block->ip & block_mask) != (curr->ip & block_mask))
return 0;
#if 0
printf("ip %d.%d.%d.%d/%d is within block %d.%d.%d.%d/%d\n",
curr->ip >> 24,
(curr->ip >> 16) & 0xff,
(curr->ip >> 8) & 0xff,
(curr->ip >> 0) & 0xff,
curr->width,
block->ip >> 24,
(block->ip >> 16) & 0xff,
(block->ip >> 8) & 0xff,
(block->ip >> 0) & 0xff,
block->width);
#endif
return 1;
}
static void
ipranges_find_b_blocks(void)
{
uint32_t last_block = 0;
uint32_t counter = 0;
uint32_t b_mask = 0xffff0000;
iprange_t* curr;
PBUF_FOREACH(curr, &black_ranges)
if (curr->obsolete)
continue;
uint32_t const curr_block = curr->ip & b_mask;
if (curr_block == last_block) {
counter++;
continue;
}
iprange_maybe_add_b_block(counter, last_block);
last_block = curr_block;
counter = 1;
PBUF_FOREACH_END
iprange_maybe_add_b_block(counter, last_block);
if (pbuf_size(&new_b_ranges) == 0)
return;
// cleanup
PBUF_FOREACH(curr, &black_ranges)
if (curr->obsolete)
continue;
iprange_t* const b_block = pbuf_find(&new_b_ranges, iprange_match_block, curr);
if (b_block)
curr->obsolete = true;
PBUF_FOREACH_END
}
int
main(int argc, const char* argv[])
{
pbuf_init(&black_ranges, 4, 0, NULL);
pbuf_init(&white_ranges, 4, 0, NULL);
pbuf_init(&new_ranges, 4, 0, NULL);
pbuf_init(&new_b_ranges, 4, 0, NULL);
iprange_load("autofw.whitelist", true);
iprange_load("autofw.blacklist", false);
(void) argc;
(void) argv;
pbuf_sort(&black_ranges, iprange_cmp);
ipranges_merge();
ipranges_find_b_blocks();
pbuf_sort(&new_ranges, iprange_cmp);
iprange_t* range;
PBUF_FOREACH(range, &black_ranges)
if (!range->obsolete)
continue;
printf("yes | ufw delete deny from %d.%d.%d.%d/%d\n",
range->ip >> 24,
(range->ip >> 16) & 0xff,
(range->ip >> 8) & 0xff,
(range->ip >> 0) & 0xff,
range->width);
PBUF_FOREACH_END
PBUF_FOREACH(range, &new_ranges)
printf("ufw insert 1 deny from %d.%d.%d.%d/%d\n",
range->ip >> 24,
(range->ip >> 16) & 0xff,
(range->ip >> 8) & 0xff,
(range->ip >> 0) & 0xff,
range->width);
PBUF_FOREACH_END
PBUF_FOREACH(range, &new_b_ranges)
printf("ufw insert 1 deny from %d.%d.%d.%d/%d\n",
range->ip >> 24,
(range->ip >> 16) & 0xff,
(range->ip >> 8) & 0xff,
(range->ip >> 0) & 0xff,
range->width);
PBUF_FOREACH_END
if (pbuf_size(&new_ranges) > 0) {
PBUF_FOREACH(range, &white_ranges)
printf("yes | ufw delete allow from %d.%d.%d.%d/%d\n",
range->ip >> 24,
(range->ip >> 16) & 0xff,
(range->ip >> 8) & 0xff,
(range->ip >> 0) & 0xff,
range->width);
printf("yes | ufw insert 1 allow from %d.%d.%d.%d/%d\n",
range->ip >> 24,
(range->ip >> 16) & 0xff,
(range->ip >> 8) & 0xff,
(range->ip >> 0) & 0xff,
range->width);
PBUF_FOREACH_END
}
pbuf_destroy(&black_ranges);
pbuf_destroy(&white_ranges);
pbuf_destroy(&new_ranges);
pbuf_destroy(&new_b_ranges);
exit(0);
}

11
matcher.h Normal file
View file

@ -0,0 +1,11 @@
#define PCRE2_CODE_UNIT_WIDTH 8
#include "pcre2.h"
#include "pbuf.h"
typedef struct {
pcre2_code* regexp;
pbuf_t results;
} regexp_matcher_t;

14
pbuf.h Normal file
View file

@ -0,0 +1,14 @@
typedef void (*pbuf_func_free_t)(void*);
typedef struct {
int used;
int allocated;
int chunksize;
void** ptr;
pbuf_func_free_t func_free;
} pbuf_t;
// Add a new item at the end of the pbuf_t.
extern void pbuf_append(pbuf_t* pbuf, void* ptr);

0
vbuf.h Normal file
View file