12 changed files with 286 additions and 4 deletions
@ -0,0 +1,95 @@ |
|||||||
|
// firewall.c - Firewall module for utun
|
||||||
|
#define _POSIX_C_SOURCE 200809L |
||||||
|
#include "firewall.h" |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include "../lib/debug_config.h" |
||||||
|
#include "../lib/mem.h" |
||||||
|
|
||||||
|
static int compare_rules(const void *a, const void *b) { |
||||||
|
const struct CFG_FIREWALL_RULE *ra = (const struct CFG_FIREWALL_RULE *)a; |
||||||
|
const struct CFG_FIREWALL_RULE *rb = (const struct CFG_FIREWALL_RULE *)b; |
||||||
|
if (ra->ip != rb->ip) { |
||||||
|
return (ra->ip > rb->ip) ? 1 : -1; |
||||||
|
} |
||||||
|
return (ra->port > rb->port) ? 1 : -1; |
||||||
|
} |
||||||
|
|
||||||
|
int fw_init(struct firewall_ctx *ctx) { |
||||||
|
if (!ctx) return -1; |
||||||
|
memset(ctx, 0, sizeof(struct firewall_ctx)); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int fw_load_rules(struct firewall_ctx *ctx, const struct global_config *cfg) { |
||||||
|
if (!ctx || !cfg) return -1; |
||||||
|
|
||||||
|
fw_free(ctx); |
||||||
|
fw_init(ctx); |
||||||
|
|
||||||
|
ctx->bypass_all = cfg->firewall_bypass_all; |
||||||
|
|
||||||
|
if (cfg->firewall_rule_count > 0) { |
||||||
|
ctx->rules = u_calloc(cfg->firewall_rule_count, sizeof(struct CFG_FIREWALL_RULE)); |
||||||
|
if (!ctx->rules) { |
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "fw_load_rules: failed to allocate rules"); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
memcpy(ctx->rules, cfg->firewall_rules,
|
||||||
|
cfg->firewall_rule_count * sizeof(struct CFG_FIREWALL_RULE)); |
||||||
|
ctx->count = cfg->firewall_rule_count; |
||||||
|
|
||||||
|
// Sort rules by IP (and port)
|
||||||
|
qsort(ctx->rules, ctx->count, sizeof(struct CFG_FIREWALL_RULE), compare_rules); |
||||||
|
|
||||||
|
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Loaded %d firewall rules (sorted)", ctx->count); |
||||||
|
} |
||||||
|
|
||||||
|
if (ctx->bypass_all) { |
||||||
|
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Firewall bypass_all mode enabled"); |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int fw_check(const struct firewall_ctx *ctx, uint32_t ip, uint16_t port) { |
||||||
|
if (!ctx) return 0; |
||||||
|
if (ctx->bypass_all) return 1; |
||||||
|
|
||||||
|
// Binary search for IP
|
||||||
|
int low = 0; |
||||||
|
int high = ctx->count - 1; |
||||||
|
while (low <= high) { |
||||||
|
int mid = (low + high) / 2; |
||||||
|
if (ctx->rules[mid].ip == ip) { |
||||||
|
// Found matching IP, check port
|
||||||
|
int i = mid; |
||||||
|
// Check exact match or any-port rule
|
||||||
|
while (i >= 0 && ctx->rules[i].ip == ip) { |
||||||
|
if (ctx->rules[i].port == 0 || ctx->rules[i].port == port) { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
i--; |
||||||
|
} |
||||||
|
i = mid + 1; |
||||||
|
while (i < ctx->count && ctx->rules[i].ip == ip) { |
||||||
|
if (ctx->rules[i].port == 0 || ctx->rules[i].port == port) { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
i++; |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} else if (ctx->rules[mid].ip < ip) { |
||||||
|
low = mid + 1; |
||||||
|
} else { |
||||||
|
high = mid - 1; |
||||||
|
} |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
void fw_free(struct firewall_ctx *ctx) { |
||||||
|
if (!ctx) return; |
||||||
|
u_free(ctx->rules); |
||||||
|
memset(ctx, 0, sizeof(struct firewall_ctx)); |
||||||
|
} |
||||||
@ -0,0 +1,27 @@ |
|||||||
|
// firewall.h - Firewall rules for utun
|
||||||
|
#ifndef FIREWALL_H |
||||||
|
#define FIREWALL_H |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
#include "config_parser.h" |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
struct firewall_ctx { |
||||||
|
struct CFG_FIREWALL_RULE *rules; |
||||||
|
int count; |
||||||
|
int bypass_all; |
||||||
|
}; |
||||||
|
|
||||||
|
int fw_init(struct firewall_ctx *ctx); |
||||||
|
int fw_load_rules(struct firewall_ctx *ctx, const struct global_config *cfg); |
||||||
|
int fw_check(const struct firewall_ctx *ctx, uint32_t ip, uint16_t port); |
||||||
|
void fw_free(struct firewall_ctx *ctx); |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif |
||||||
Loading…
Reference in new issue