mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-25 16:52:29 +00:00
Turn the networking stubs into a working transport/application stack on top of
the existing L2/L3 (Ethernet/ARP/IPv4/ICMP) core.
UDP (net/ipv4/udp.c)
- Port-demux table with bound receive handlers, pseudo-header checksum,
ephemeral-port allocation, limited-broadcast send (0.0.0.0 -> 255.255.255.255
for DHCP before the interface has an address), and rx/tx/drop counters.
- Wired into the IPv4 receive path (IP_PROTO_UDP dispatch in net/core/net.c).
BSD sockets (net/core/socket.c)
- Real SOCK_DGRAM sockets backed by UDP: bind installs a UDP handler that fills
a per-socket receive ring; send/sendto and recv/recvfrom move datagrams;
ephemeral auto-bind, connect() memorises the peer. Socket table + I/O stats
exposed for introspection.
DNS resolver (net/ipv4/dns.c)
- Builds and parses real A-record queries over UDP/53 (label encoding,
compression-pointer aware answer walk), cache-first with TTL, static-hosts
and dotted-quad fast paths, and a bounded timeout that degrades to fallback
instead of hanging.
DHCP client (net/ipv4/dhcp.c)
- Full DISCOVER/OFFER/REQUEST/ACK handshake over UDP broadcast, option parsing
(mask/router/dns/lease/server-id), applies the lease to the primary
interface, bounded timeouts keep the static config on no response.
Fix (net/ipv4/dns_cache.c): the cache stored IPs as 0xAABBCCDD numeric while the
rest of the stack uses network-byte-order-in-memory (ip_parse/ip_to_str), so a
resolved address came back byte-swapped (nslookup github.com -> 100.121.82.140).
Seeds and dump now use ip_parse/ip_to_str; verified 140.82.121.4.
Userland (lazybox): live ifconfig (real interface + NIC counters, loopback),
netstat with live UDP bindings and transport stats, new `sockstat`, richer
nslookup. Verified in QEMU: boot clean on x86_64/aarch64/armv8i, login as SUB,
ping/nslookup/dhclient/netstat/sockstat all run; DHCP/DNS wire replies are
blocked by the sandbox's slirp but time out cleanly and fall back as designed.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Fh5z6V7nGPbHvqVG5p4CXX
97 lines
3.8 KiB
C
97 lines
3.8 KiB
C
// DNS Resolver Cache with TTL Management and Metrics for SUB-OS.
|
|
//
|
|
// IPs are stored in the same convention as the rest of the network stack:
|
|
// network byte order in memory (the first octet in the lowest byte), exactly as
|
|
// produced by ip_parse() and consumed by ip_to_str(). Storing them any other
|
|
// way would hand dns_resolve() callers a byte-swapped address.
|
|
#include <net/dns_cache.h>
|
|
#include <net/net.h>
|
|
#include <lib/string.h>
|
|
#include <lib/printf.h>
|
|
#include <kernel/printk.h>
|
|
|
|
static dns_cache_entry_t dns_table[DNS_CACHE_MAX_ENTRIES];
|
|
static uint64_t total_lookups = 0;
|
|
static uint64_t total_hits = 0;
|
|
|
|
void dns_cache_init(void) {
|
|
memset(dns_table, 0, sizeof(dns_table));
|
|
// Seed common local and well-known hosts (network byte order via ip_parse).
|
|
dns_cache_insert("localhost", ip_parse("127.0.0.1"), 86400);
|
|
dns_cache_insert("gateway.local", ip_parse("10.0.2.2"), 3600);
|
|
dns_cache_insert("dns.google", ip_parse("8.8.8.8"), 7200);
|
|
dns_cache_insert("one.one.one.one", ip_parse("1.1.1.1"), 7200);
|
|
dns_cache_insert("github.com", ip_parse("140.82.121.4"), 300);
|
|
|
|
printk(KERN_INFO "DNS: High-performance DNS Cache table initialized (Capacity: %d)\n", DNS_CACHE_MAX_ENTRIES);
|
|
}
|
|
|
|
bool dns_cache_lookup(const char* hostname, uint32_t* out_ip) {
|
|
if (!hostname || !out_ip) return false;
|
|
total_lookups++;
|
|
|
|
for (int i = 0; i < DNS_CACHE_MAX_ENTRIES; i++) {
|
|
if (dns_table[i].active && strcmp(dns_table[i].hostname, hostname) == 0) {
|
|
dns_table[i].hit_count++;
|
|
total_hits++;
|
|
*out_ip = dns_table[i].ip;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void dns_cache_insert(const char* hostname, uint32_t ip, uint32_t ttl) {
|
|
if (!hostname) return;
|
|
|
|
// Update existing entry if present
|
|
for (int i = 0; i < DNS_CACHE_MAX_ENTRIES; i++) {
|
|
if (dns_table[i].active && strcmp(dns_table[i].hostname, hostname) == 0) {
|
|
dns_table[i].ip = ip;
|
|
dns_table[i].ttl_remaining = ttl;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Insert in first free slot
|
|
for (int i = 0; i < DNS_CACHE_MAX_ENTRIES; i++) {
|
|
if (!dns_table[i].active) {
|
|
strncpy(dns_table[i].hostname, hostname, DNS_CACHE_MAX_HOST - 1);
|
|
dns_table[i].hostname[DNS_CACHE_MAX_HOST - 1] = '\0';
|
|
dns_table[i].ip = ip;
|
|
dns_table[i].ttl_remaining = ttl ? ttl : 300;
|
|
dns_table[i].hit_count = 0;
|
|
dns_table[i].active = true;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void dns_cache_flush(void) {
|
|
memset(dns_table, 0, sizeof(dns_table));
|
|
dns_cache_insert("localhost", ip_parse("127.0.0.1"), 86400);
|
|
printk(ANSI_YELLOW "DNS: Resolver cache flushed.\n" ANSI_RESET);
|
|
}
|
|
|
|
void dns_cache_dump(void) {
|
|
printk(ANSI_BRIGHT_CYAN "=== SUB-OS In-Kernel DNS Cache & Metrics ===\n" ANSI_RESET);
|
|
uint32_t hit_ratio = (total_lookups > 0) ? (uint32_t)((total_hits * 100) / total_lookups) : 0;
|
|
printk(" Total Lookups: " ANSI_YELLOW "%llu" ANSI_RESET " Hits: " ANSI_BRIGHT_GREEN "%llu" ANSI_RESET " Hit Ratio: " ANSI_BRIGHT_GREEN "%u%%\n" ANSI_RESET,
|
|
total_lookups, total_hits, hit_ratio);
|
|
printk("-----------------------------------------------------------------\n");
|
|
printk(ANSI_BOLD "%-28s %-16s %8s %8s\n" ANSI_RESET, "HOSTNAME", "IP ADDRESS", "TTL (s)", "HITS");
|
|
printk("-----------------------------------------------------------------\n");
|
|
|
|
for (int i = 0; i < DNS_CACHE_MAX_ENTRIES; i++) {
|
|
if (dns_table[i].active) {
|
|
char ip_str[20];
|
|
ip_to_str(dns_table[i].ip, ip_str);
|
|
|
|
printk("%-28s " ANSI_BRIGHT_YELLOW "%-16s" ANSI_RESET " %8u %8llu\n",
|
|
dns_table[i].hostname, ip_str,
|
|
dns_table[i].ttl_remaining, dns_table[i].hit_count);
|
|
}
|
|
}
|
|
printk("\n");
|
|
}
|