merge again if any new ranges were added

This commit is contained in:
Daniel Brahneborg 2025-12-07 11:38:10 +01:00
parent 34d88d8ec5
commit 45ce884264

View file

@ -21,6 +21,7 @@ fclose_ptr(FILE** p)
typedef struct { typedef struct {
bool obsolete; bool obsolete;
bool is_new;
uint32_t ip; uint32_t ip;
uint8_t width; uint8_t width;
} iprange_t; } iprange_t;
@ -111,7 +112,7 @@ iprange_cmp(const void* a, const void* b)
return 0; return 0;
} }
static void static bool
iprange_join(iprange_t* prev, iprange_t* curr) iprange_join(iprange_t* prev, iprange_t* curr)
{ {
uint32_t const prev_mask = ~0U << (32 - prev->width); uint32_t const prev_mask = ~0U << (32 - prev->width);
@ -122,7 +123,7 @@ iprange_join(iprange_t* prev, iprange_t* curr)
#endif #endif
if ((prev->ip & prev_mask) == (curr->ip & prev_mask)) { if ((prev->ip & prev_mask) == (curr->ip & prev_mask)) {
curr->obsolete = true; curr->obsolete = true;
return; return false;
} }
int min_width = prev->width < curr->width ? prev->width : curr->width; int min_width = prev->width < curr->width ? prev->width : curr->width;
if (min_width < 8) if (min_width < 8)
@ -131,14 +132,14 @@ iprange_join(iprange_t* prev, iprange_t* curr)
// printf("widths: min %d max %d\n", min_width, max_width); // printf("widths: min %d max %d\n", min_width, max_width);
if (max_width - min_width > 8) { if (max_width - min_width > 8) {
// printf("width difference %d, too much\n", max_width - min_width); // printf("width difference %d, too much\n", max_width - min_width);
return; return false;
} }
int new_width = max_width; int new_width = max_width;
uint32_t new_mask = 0; uint32_t new_mask = 0;
for (;;) { for (;;) {
if ((new_width <= 8) || (max_width - new_width > 8)) { if ((new_width <= 8) || (max_width - new_width > 8)) {
// printf("nothing in common with at least 8 bits\n"); // printf("nothing in common with at least 8 bits\n");
return; return false;
} }
new_width = new_width - 1; new_width = new_width - 1;
new_mask = ~0U << (32 - new_width); new_mask = ~0U << (32 - new_width);
@ -152,14 +153,24 @@ iprange_join(iprange_t* prev, iprange_t* curr)
break; break;
if (!(new_width & 7)) { if (!(new_width & 7)) {
// printf("too far apart, giving up\n"); // printf("too far apart, giving up\n");
return; return false;
} }
} }
uint32_t const new_ip = prev->ip & new_mask; uint32_t const new_ip = prev->ip & new_mask;
#if 0
printf("adding new range %d.%d.%d.%d/%d\n",
new_ip >> 24,
(new_ip >> 16) & 0xff,
(new_ip >> 8) & 0xff,
(new_ip >> 0) & 0xff,
new_width);
#endif
iprange_t* const range = iprange_create(new_ip, new_width); iprange_t* const range = iprange_create(new_ip, new_width);
range->is_new = true;
pbuf_append(&new_ranges, range); pbuf_append(&new_ranges, range);
prev->obsolete = true; prev->obsolete = true;
curr->obsolete = true; curr->obsolete = true;
return true;
} }
static void static void
@ -167,6 +178,8 @@ ipranges_merge(void)
{ {
iprange_t* prev = NULL; iprange_t* prev = NULL;
iprange_t* curr; iprange_t* curr;
bool added_something = false;
pbuf_sort(&black_ranges, iprange_cmp);
PBUF_FOREACH(curr, &black_ranges) PBUF_FOREACH(curr, &black_ranges)
if (!prev) { if (!prev) {
prev = curr; prev = curr;
@ -185,10 +198,16 @@ ipranges_merge(void)
(curr->ip >> 0) & 0xff, (curr->ip >> 0) & 0xff,
curr->width); curr->width);
#endif #endif
iprange_join(prev, curr); if (iprange_join(prev, curr))
added_something = true;
if (!curr->obsolete) if (!curr->obsolete)
prev = curr; prev = curr;
PBUF_FOREACH_END PBUF_FOREACH_END
if (!added_something)
return;
pbuf_appendall(&black_ranges, &new_ranges);
pbuf_clear(&new_ranges);
ipranges_merge();
} }
static void static void
@ -271,7 +290,7 @@ main(int argc, const char* argv[])
{ {
pbuf_init(&black_ranges, 4, 0, NULL); pbuf_init(&black_ranges, 4, 0, NULL);
pbuf_init(&white_ranges, 4, 0, NULL); pbuf_init(&white_ranges, 4, 0, NULL);
pbuf_init(&new_ranges, 4, 0, NULL); pbuf_init(&new_ranges, 4, 0, PBUF_NONE);
pbuf_init(&new_b_ranges, 4, 0, NULL); pbuf_init(&new_b_ranges, 4, 0, NULL);
iprange_load("autofw.whitelist", true); iprange_load("autofw.whitelist", true);
@ -280,7 +299,6 @@ main(int argc, const char* argv[])
(void) argc; (void) argc;
(void) argv; (void) argv;
pbuf_sort(&black_ranges, iprange_cmp);
ipranges_merge(); ipranges_merge();
ipranges_find_b_blocks(); ipranges_find_b_blocks();
@ -288,7 +306,7 @@ main(int argc, const char* argv[])
iprange_t* range; iprange_t* range;
PBUF_FOREACH(range, &black_ranges) PBUF_FOREACH(range, &black_ranges)
if (!range->obsolete) if (!range->obsolete || range->is_new)
continue; continue;
printf("yes | ufw delete deny from %d.%d.%d.%d/%d\n", printf("yes | ufw delete deny from %d.%d.%d.%d/%d\n",
range->ip >> 24, range->ip >> 24,
@ -298,7 +316,11 @@ main(int argc, const char* argv[])
range->width); range->width);
PBUF_FOREACH_END PBUF_FOREACH_END
PBUF_FOREACH(range, &new_ranges) bool something_new = false;
PBUF_FOREACH(range, &black_ranges)
if (range->obsolete || !range->is_new)
continue;
something_new = true;
printf("ufw insert 1 deny from %d.%d.%d.%d/%d\n", printf("ufw insert 1 deny from %d.%d.%d.%d/%d\n",
range->ip >> 24, range->ip >> 24,
(range->ip >> 16) & 0xff, (range->ip >> 16) & 0xff,
@ -316,7 +338,7 @@ main(int argc, const char* argv[])
range->width); range->width);
PBUF_FOREACH_END PBUF_FOREACH_END
if (pbuf_size(&new_ranges) > 0) { if (something_new) {
PBUF_FOREACH(range, &white_ranges) PBUF_FOREACH(range, &white_ranges)
printf("yes | ufw delete allow from %d.%d.%d.%d/%d\n", printf("yes | ufw delete allow from %d.%d.%d.%d/%d\n",
range->ip >> 24, range->ip >> 24,