Files
subhobhai943andClaude Opus 4.8 cd840d5799 feat(net): real UDP transport, BSD datagram sockets, DNS resolver, DHCP client
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
2026-08-26 10:20:58 +05:30

40 lines
1.6 KiB
C

#ifndef _NET_UDP_H
#define _NET_UDP_H
#include <net/net.h>
// A bound UDP port dispatches every matching datagram to this callback. It runs
// in soft-IRQ / receive context, so handlers must be quick and non-blocking:
// stash the datagram and set a completion flag, then process it from a thread.
typedef void (*udp_handler_t)(uint32_t src_ip, uint16_t src_port,
uint16_t dst_port, const uint8_t* data,
uint16_t len, void* ctx);
void udp_init(void);
// Demultiplex an inbound IPv4 payload (protocol 17) to a bound port.
void udp_receive(const uint8_t* packet, uint16_t length, uint32_t src_ip);
// Emit a datagram to dst_ip:dst_port from src_port (checksummed).
void udp_send(uint32_t dst_ip, uint16_t src_port, uint16_t dst_port,
const void* data, uint16_t len);
// Emit a datagram to the limited broadcast address (255.255.255.255) from
// source IP 0.0.0.0 — used before the interface has an address (DHCP).
void udp_send_broadcast(uint16_t src_port, uint16_t dst_port,
const void* data, uint16_t len);
// Register/unregister a receive handler for a local port. udp_bind returns 0 on
// success, -1 if the port is taken or the table is full.
int udp_bind(uint16_t port, udp_handler_t handler, void* ctx);
void udp_unbind(uint16_t port);
// Allocate an unused ephemeral port in the 49152-65535 range.
uint16_t udp_alloc_ephemeral_port(void);
// Counters: datagrams received, transmitted, and dropped (no listener / bad).
void udp_get_stats(uint64_t* rx, uint64_t* tx, uint64_t* drop);
int udp_get_bindings(uint16_t* ports_out, int max);
#endif // _NET_UDP_H