reject invalid routes
This commit is contained in:
@@ -11,11 +11,13 @@ uint8_t IPUtils_MaskToCIDRv4(uint32_t mask);
|
||||
bool IPUtils_MatchPrefixv4(uint32_t ip, uint32_t prefix, uint8_t cidr);
|
||||
// If buf is NULL, -> stdout; if NOT NULL, -> buf (must be at least 16 bytes)
|
||||
void IPUtils_PrintIPv4(uint32_t ip, char* buf);
|
||||
bool IPUtils_IsInSubnetv4(uint32_t ip, uint32_t subnet, uint32_t mask);
|
||||
|
||||
__uint128_t IPUtils_CIDRToMaskv6(uint8_t cidr);
|
||||
uint8_t IPUtils_MaskToCIDRv6(__uint128_t mask);
|
||||
bool IPUtils_MatchPrefixv6(__uint128_t ip, __uint128_t prefix, uint8_t cidr);
|
||||
// If buf is NULL, -> stdout; if NOT NULL, -> buf (must be at least 40 bytes)
|
||||
void IPUtils_PrintIPv6(__uint128_t ip, char* buf);
|
||||
bool IPUtils_IsInSubnetv6(__uint128_t ip, __uint128_t subnet, __uint128_t mask);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,6 +31,7 @@ static int free_value_cb(void *data, const unsigned char *key, uint32_t key_len,
|
||||
}
|
||||
|
||||
int RouteTable_Init(void) {
|
||||
// Create the ART trees for the IPv4 and the IPv6 route tables
|
||||
if (art_tree_init(&route_table_v4) != 0) return -1;
|
||||
if (art_tree_init(&route_table_v6) != 0) {
|
||||
art_tree_destroy(&route_table_v4);
|
||||
@@ -40,6 +41,7 @@ int RouteTable_Init(void) {
|
||||
}
|
||||
|
||||
void RouteTable_Cleanup(void) {
|
||||
// Iterate clean the tables and destroy them
|
||||
art_iter(&route_table_v4, free_value_cb, NULL);
|
||||
art_tree_destroy(&route_table_v4);
|
||||
art_iter(&route_table_v6, free_value_cb, NULL);
|
||||
@@ -47,9 +49,12 @@ void RouteTable_Cleanup(void) {
|
||||
}
|
||||
|
||||
int RouteTable_AddRoute_v4(uint32_t destination, uint32_t mask, uint32_t nextHop) {
|
||||
if (destination == 0 || nextHop == 0 || mask == 0) return -1;
|
||||
if (destination == 0 || nextHop == 0 || mask == 0) return -1; // Reject invalid routes (e.g., zero next hop or mask)
|
||||
|
||||
if (destination == 0x7F000001) return -1;
|
||||
// Common subnet checks
|
||||
if (IPUtils_IsInSubnetv4(destination, 0x7F000000, 0xFF000000)) return -1; // Reject loopback
|
||||
if (IPUtils_IsInSubnetv4(destination, 0xF0000000, 0xF0000000)) return -1; // Reject class E
|
||||
// Note: Private IPs are allowed because those have legitimate use cases
|
||||
|
||||
uint8_t prefix_len = IPUtils_MaskToCIDRv4(mask);
|
||||
uint32_t network = destination & mask;
|
||||
@@ -70,7 +75,7 @@ int RouteTable_AddRoute_v4(uint32_t destination, uint32_t mask, uint32_t nextHop
|
||||
int RouteTable_AddRoute_v6(__uint128_t destination, __uint128_t mask, __uint128_t nextHop) {
|
||||
if (destination == 0 || nextHop == 0 || mask == 0) return -1;
|
||||
|
||||
if (destination == (__uint128_t)1) return -1;
|
||||
if (destination == (__uint128_t)1) return -1; // Reject loopback (::1)
|
||||
|
||||
uint8_t prefix_len = IPUtils_MaskToCIDRv6(mask);
|
||||
__uint128_t network = destination & mask;
|
||||
|
||||
@@ -38,6 +38,10 @@ void IPUtils_PrintIPv4(uint32_t ip, char* buf) {
|
||||
}
|
||||
}
|
||||
|
||||
bool IPUtils_IsInSubnetv4(uint32_t ip, uint32_t subnet, uint32_t mask) {
|
||||
return (ip & mask) == (subnet & mask);
|
||||
}
|
||||
|
||||
__uint128_t IPUtils_CIDRToMaskv6(uint8_t cidr) {
|
||||
if (cidr > 128) { return 0x00; }
|
||||
__uint128_t mask = 0;
|
||||
@@ -87,3 +91,7 @@ void IPUtils_PrintIPv6(__uint128_t ip, char* buf) {
|
||||
(unsigned int)(ip & 0xFFFF));
|
||||
}
|
||||
}
|
||||
|
||||
bool IPUtils_IsInSubnetv6(__uint128_t ip, __uint128_t subnet, __uint128_t mask) {
|
||||
return (ip & mask) == (subnet & mask);
|
||||
}
|
||||
|
||||
@@ -24,11 +24,16 @@ void Log_Cleanup() {
|
||||
}
|
||||
|
||||
static void log_emit(FILE* stream, const char* level, const char* fmt, va_list ap) {
|
||||
// Get UNIX millis
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
unsigned long timestamp = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
||||
|
||||
char msg[1024];
|
||||
vsnprintf(msg, sizeof(msg), fmt, ap);
|
||||
|
||||
char buf[1024];
|
||||
int len = snprintf(buf, sizeof(buf), "[%s] %s\n", level, msg);
|
||||
int len = snprintf(buf, sizeof(buf), "[%lu] [%s] %s\n", timestamp, level, msg);
|
||||
fputs(buf, stream);
|
||||
if (log_socket_fd >= 0)
|
||||
sendto(log_socket_fd, buf, len, 0, (struct sockaddr*)&log_dest, sizeof(log_dest));
|
||||
|
||||
@@ -64,6 +64,13 @@ int main(void) {
|
||||
Log_Err("Failed to get next hop for destination %s", destStr);
|
||||
}
|
||||
|
||||
// Attempt to add class E route (should be rejected)
|
||||
if (RouteTable_AddRoute_v4(0xF0000001, 0xF0000000, 0xC0A80101) < 0) {
|
||||
Log_Info("Correctly rejected invalid class E route");
|
||||
} else {
|
||||
Log_Err("Incorrectly accepted invalid class E route");
|
||||
}
|
||||
|
||||
// Some IPv6 routes
|
||||
__uint128_t dest6 = (((__uint128_t)0x20010DB8 << 96) | ((__uint128_t)0x00000000 << 64) | ((__uint128_t)0x00000000 << 32) | (__uint128_t)0x00000001); // 2001:0db8::1
|
||||
__uint128_t mask6 = IPUtils_CIDRToMaskv6(64);
|
||||
|
||||
Reference in New Issue
Block a user