diff --git a/include/iputils.h b/include/iputils.h index a2c6316..86cc9f2 100644 --- a/include/iputils.h +++ b/include/iputils.h @@ -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 diff --git a/src/forward/routetable.c b/src/forward/routetable.c index 98d01be..10dc0e3 100644 --- a/src/forward/routetable.c +++ b/src/forward/routetable.c @@ -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; diff --git a/src/iputils.c b/src/iputils.c index 9bc9832..12983cf 100644 --- a/src/iputils.c +++ b/src/iputils.c @@ -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); +} diff --git a/src/log.c b/src/log.c index a596210..d33004a 100644 --- a/src/log.c +++ b/src/log.c @@ -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)); diff --git a/src/main.c b/src/main.c index 26e9b55..83b159a 100644 --- a/src/main.c +++ b/src/main.c @@ -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);