Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b3304e6
[IPV6]adde helpers (not fully tested), minor changes
CodeAnarchist Oct 26, 2025
13e79dd
[IPV6] send packet and input
CodeAnarchist Oct 27, 2025
b62a094
[net] ipv6, ndp, tcp and various improvements
CodeAnarchist Dec 20, 2025
45cdf6b
[NET]added non working dhcpv6, fixed minor bugs
CodeAnarchist Dec 22, 2025
48ec612
[net]add stateless dhcpv6, rdnss, minor improvements
CodeAnarchist Dec 22, 2025
316d66e
[net] clean up interface selection in sockets
CodeAnarchist Dec 22, 2025
4c0dd95
[net] improve tcp, update tcp socket and application layer protocols
CodeAnarchist Dec 25, 2025
4a16f6f
[net]update interface id generation
CodeAnarchist Dec 25, 2025
9cd2229
[net] add ping v6 and minor improvements
CodeAnarchist Dec 27, 2025
5a7c104
[net]add netpkt abstraction and integration in the network stack
CodeAnarchist Dec 27, 2025
6a82344
[net] localhost fix and minor improvements
CodeAnarchist Dec 29, 2025
8aa8705
[misc] added shutdown, console improvements (small bug present)
CodeAnarchist Dec 30, 2025
f76aaa5
[console] fixed the bug
CodeAnarchist Dec 30, 2025
b567f87
[console] add software key repeat for back/del
CodeAnarchist Dec 30, 2025
13800ec
[net]minor changes
CodeAnarchist Dec 31, 2025
76893e3
[net] introduce socket extra options, added base debug logging
CodeAnarchist Jan 1, 2026
6b91540
[net] improved logs
CodeAnarchist Jan 1, 2026
6fc8e7b
[net] double free, minor fixes
CodeAnarchist Jan 2, 2026
0581573
[net] added additional socket options (untested)
CodeAnarchist Jan 2, 2026
7e4e516
[net] add basic igmp/mcast ipv4 management
CodeAnarchist Jan 2, 2026
0ca33b9
[net] improved ipv4 multicast management, added basic igmp, ssdp
CodeAnarchist Jan 3, 2026
af7a236
[net] mdns
CodeAnarchist Jan 3, 2026
1b47641
[net] dns, mdns, dns sd, mld
CodeAnarchist Jan 5, 2026
f2cb4ee
[net] mon:stdio
CodeAnarchist Jan 5, 2026
f181efa
[net] various fixes, ntp
CodeAnarchist Jan 8, 2026
6f8dd0c
[net]minore fixes, tcp stream-like is not working
CodeAnarchist Jan 8, 2026
db05ed1
Merge remote-tracking branch 'upstream/main' into ipv6
CodeAnarchist Jan 9, 2026
0d1c775
Merge remote-tracking branch 'upstream/main' into ipv6
CodeAnarchist Jan 11, 2026
3f7bd4b
[net/drivers] virtio pci update, merge, minor fixes
CodeAnarchist Jan 11, 2026
7baf42b
[net] minor fixes
CodeAnarchist Jan 13, 2026
8ae8bd1
Merge remote-tracking branch 'upstream/main' into ipv6
CodeAnarchist Jan 14, 2026
e693c1b
[net] improved keyboard, updated readme
CodeAnarchist Jan 14, 2026
06e0815
[dns] relocated dns files
CodeAnarchist Jan 14, 2026
aa0682a
[misc]
CodeAnarchist Jan 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,21 @@ The Raspberry Pi emulation has the following limitations:

## Networking

The system provides medium level networking support. At startup, it scans for available network cards, loads the matching driver if present and creates a logical L2 interface for each device; a loopback interface is also added for both IPv4 and IPv6, though the current loopback implementation is partial and rejects all localhost packets. IPv4 networking is fully implemented, while IPv6 support is limited to interface structures and it cannot perform real communication.
Once interfaces and dispatcher are initialized, the system starts ARP, DHCP, DNS and SNTP processes. At the moment, SNTP sets the unix time and the time zone is configured manually since DHCP options 100 and 101 are not always included.
The stack supports UDP and TCP sockets, and an HTTP socket is implemented on top of TCP. ICMP is also supported with the system able to respond to ping requests. DNS resolution can be called directly by applications and is also used by sockets.
The system provides medium level networking support. At startup, it scans for available network cards, loads the matching driver if present and creates a logical L2 interface for each device; a loopback interface is also added for both IPv4 and IPv6.

The stack follows a layered design. At link level it handles basic neighbor resolution (ARP for IPv4 and NDP for IPv6).

on top of that the stack provides full IPv4 support and a solid IPv6 implementation. Both protocols include routing support and the related control via ICMP and ICMPv6. IPv6 is already usable in practice and covers the core features needed for normal operation; some more advanced pieces are missing (such as full SLAAC support, router preference handling, complete set of extension header features, ULA)

Multicast is supported and traffic is filtered at the NIC level to avoid unnecessary delivery and group membership; announcements are made through IGMP for Ipv4 and MLD for IPv6 keeping multicast use clean and controlled

For address config the system provides small APIs based on DHCP for IPv4 and DHCPv6 stateful, stateless and SLAAC for IPv6, allowing interfaces to be configured automatically without special handling in applications.

For name resolution a DNS resolver is available, backed by an internal cache to reduce latency and unnecessary network interrupts. also service discovery on the local network is supported in a lightweight form via DNS SD/mDNS responders and SSDP utilities(currently disabled).

time sync is provided through an NTP based service. The current implementation is not fully standards compliant but it is designed to be as accurate as possible for the time being, focusing on correct offset calculation and stable clock adjustments rather than full protocol coverage. SNTP is also present for compatibility, but it is considered deprecated and kept for legacy.

apps can interact with the network through a socket-oriented interface. UDP and TCP sockets are supported and a small HTTP layer is available both as a client and server

An embedded HTTP server is included and listens on port 80, serving a minimal page. Also discovery mechanism is available: the system probes the local network via UDP broadcast on port 8080, and when a responder replies it connects via HTTP on port 80, though it currently does nothing noteworthy.
An implementation of the server can be found at the [RedactedOS Firmware Server Repository](https://github.com/differrari/RedactedOS_firmware_server/tree/main)
2 changes: 2 additions & 0 deletions kernel/bin/bin_mod.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "bin_mod.h"
#include "ping.h"
#include "shutdown.h"
#include "tracert.h"
#include "monitor_processes.h"
#include "kernel_processes/kprocess_loader.h"
Expand All @@ -22,6 +23,7 @@ typedef struct open_bin_ref {

open_bin_ref available_cmds[] = {
{ "ping", run_ping },
{ "shutdown", run_shutdown },
{ "tracert", run_tracert },
{ "monitor", monitor_procs },
};
Expand Down
172 changes: 119 additions & 53 deletions kernel/bin/ping.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
#include "syscalls/syscalls.h"
#include "networking/internet_layer/ipv4.h"
#include "networking/internet_layer/ipv4_route.h"
#include "networking/application_layer/dns.h"
#include "networking/application_layer/dns/dns.h"
#include "networking/internet_layer/ipv4_utils.h"
#include "networking/internet_layer/ipv6_utils.h"
#include "networking/internet_layer/icmpv6.h"

typedef struct {
ip_version_t ver;
Expand Down Expand Up @@ -75,6 +77,23 @@ static bool parse_args(int argc, char *argv[], ping_opts_t *o) {
return true;
}

static const char *status_to_msg(uint8_t st) {
switch (st) {
case PING_TIMEOUT: return "Request timed out.";
case PING_NET_UNREACH: return "Destination Net Unreachable.";
case PING_HOST_UNREACH: return "Destination Host Unreachable.";
case PING_PROTO_UNREACH: return "Protocol Unreachable.";
case PING_PORT_UNREACH: return "Port Unreachable.";
case PING_FRAG_NEEDED: return "Fragmentation Needed.";
case PING_SRC_ROUTE_FAILED: return "Source Route Failed.";
case PING_ADMIN_PROHIBITED: return "Administratively Prohibited.";
case PING_TTL_EXPIRED: return "Time To Live exceeded.";
case PING_PARAM_PROBLEM: return "Parameter Problem.";
case PING_REDIRECT: return "Redirect received.";
default: return "No reply (unknown error).";
}
}

static int ping_v4(file *fd, const ping_opts_t *o) {
const char *host = o->host;

Expand All @@ -100,40 +119,33 @@ static int ping_v4(file *fd, const ping_opts_t *o) {
write_file(fd, host, strlen_max(host, STRING_MAX_LEN));
write_file(fd, " (", 2);
write_file(fd, ipstr, strlen_max(ipstr, STRING_MAX_LEN));
write_file(fd, ") with 32 bytes of data:", 25);
write_file(fd, "\n", 1);
write_file(fd, ") with 32 bytes of data:\n", 26);

uint32_t sent = 0, received = 0, min_ms = UINT32_MAX, max_ms = 0;
uint64_t sum_ms = 0;
uint16_t id = (uint16_t)(get_current_proc_pid() & 0xFFFF);
uint16_t seq_base = (uint16_t)(get_time() & 0xFFFF);

int8_t bound_index = -1;
ipv4_tx_opts_t txo = {0};
const ipv4_tx_opts_t *txop = NULL;
if (o->src_set) {
l3_ipv4_interface_t *l3 = l3_ipv4_find_by_ip(o->src_ip);
//kprintf("%d", l3);
if (!l3) {
const char *em = "ping: invalid source (no local ip match)\n";
write_file(fd, em, strlen_max(em, STRING_MAX_LEN));
return 2;
}

bound_index = (int8_t)l3->l3_id;
txo.index = (uint8_t)bound_index;
txo.scope = IPV4_TX_BOUND_L3;
txo.index = (uint8_t)l3->l3_id;
txo.scope = IP_TX_BOUND_L3;
txop = &txo;
char ssrc[16];
ipv4_to_string(o->src_ip, ssrc);
}

for (uint32_t i = 0; i < o->count; i++) {
++sent;
uint16_t seq = (uint16_t)(seq_base + i);

ping_result_t res = {0};
bool ok = icmp_ping(dst_ip_be, id, seq, o->timeout_ms, txop, o->ttl, &res);
bool ok = icmp_ping(dst_ip_be, id, seq, o->timeout_ms, txop, (uint8_t)o->ttl, &res);

if (ok) {
++received;
Expand All @@ -146,46 +158,93 @@ static int ping_v4(file *fd, const ping_opts_t *o) {
write_file(fd, "\n", 1);
free_sized(ln.data, ln.mem_length);
} else {
const char *msg = NULL;
if (res.status == PING_TIMEOUT) msg = "Request timed out.";
else {
switch (res.status) {
case PING_NET_UNREACH:
msg = "Destination Net Unreachable.";
break;
case PING_HOST_UNREACH:
msg = "Destination Host Unreachable.";
break;
case PING_PROTO_UNREACH:
msg = "Protocol Unreachable.";
break;
case PING_PORT_UNREACH:
msg = "Port Unreachable.";
break;
case PING_FRAG_NEEDED:
msg = "Fragmentation Needed.";
break;
case PING_SRC_ROUTE_FAILED:
msg = "Source Route Failed.";
break;
case PING_ADMIN_PROHIBITED:
msg = "Administratively Prohibited.";
break;
case PING_TTL_EXPIRED:
msg = "Time To Live exceeded.";
break;
case PING_PARAM_PROBLEM:
msg = "Parameter Problem.";
break;
case PING_REDIRECT:
msg = "Redirect received.";
break;
default:
msg = "No reply (unknown error).";
break;
}
}
write_file(fd, msg, strlen_max(msg, STRING_MAX_LEN));
const char *msg = status_to_msg(res.status);
write_file(fd, msg, strlen(msg));
write_file(fd, "\n", 1);
}

if (i + 1 < o->count) msleep(o->interval_ms);
}

write_file(fd, "\n", 1);

string h = string_format("--- %s ping statistics ---", host);
write_file(fd, h.data, h.length);
write_file(fd, "\n", 1);
free_sized(h.data, h.mem_length);

uint32_t loss = (sent == 0) ? 0 : (uint32_t)((((uint64_t)(sent - received)) * 100) / sent);
uint32_t total_time = (o->count > 0) ? (o->count - 1) * o->interval_ms : 0;

string s = string_format("%u packets transmitted, %u received, %u%% packet loss, time %ums", sent, received, loss, total_time);
write_file(fd, s.data, s.length);
write_file(fd, "\n", 1);
free_sized(s.data, s.mem_length);

if (received > 0) {
uint32_t avg = (uint32_t)(sum_ms / received);
if (min_ms == UINT32_MAX) min_ms = avg;
string r = string_format("rtt min/avg/max = %u/%u/%u ms", min_ms, avg, max_ms);
write_file(fd, r.data, r.length);
write_file(fd, "\n", 1);
free_sized(r.data, r.mem_length);
}

return (received > 0) ? 0 : 1;
}

static int ping_v6(file *fd, const ping_opts_t *o) {
const char *host = o->host;

uint8_t dst6[16] ={0};
bool is_lit = ipv6_parse(host, dst6);
if (!is_lit) {
dns_result_t dr = dns_resolve_aaaa(host, dst6, DNS_USE_BOTH, o->timeout_ms);
if (dr != DNS_OK) {
string m = string_format("ping: dns lookup failed (%d) for '%s'",(int)dr, host);
write_file(fd, m.data, m.length);
write_file(fd, "\n", 1);
free_sized(m.data, m.mem_length);
return 2;
}
}

char ipstr[64];
ipv6_to_string(dst6, ipstr, (int)sizeof(ipstr));

write_file(fd, "PING ", 5);
write_file(fd, host, strlen(host));
write_file(fd, " (", 2);
write_file(fd, ipstr, strlen(ipstr));
write_file(fd, ") with 32 bytes of data:", 25);
write_file(fd, "\n", 1);

uint32_t sent = 0, received = 0, min_ms = UINT32_MAX, max_ms = 0;
uint64_t sum_ms = 0;
uint16_t id = (uint16_t)(get_current_proc_pid() & 0xFFFF);
uint16_t seq_base = (uint16_t)(get_time() & 0xFFFF);

for (uint32_t i = 0; i < o->count; i++) {
++sent;
uint16_t seq = (uint16_t)(seq_base + i);

ping6_result_t res = {0};
bool ok = icmpv6_ping(dst6, id, seq, o->timeout_ms, NULL, (uint8_t)o->ttl, &res);

if (ok) {
++received;
uint32_t rtt = res.rtt_ms;
if (rtt < min_ms) min_ms = rtt;
if (rtt > max_ms) max_ms = rtt;
sum_ms += rtt;

string ln = string_format("Reply from %s: bytes=32 time=%ums", ipstr, (uint32_t)rtt);
write_file(fd, ln.data, ln.length);
write_file(fd, "\n", 1);
free_sized(ln.data, ln.mem_length);
} else {
const char *msg = status_to_msg(res.status);
write_file(fd, msg, strlen(msg));
write_file(fd, "\n", 1);
}

Expand Down Expand Up @@ -234,6 +293,13 @@ int run_ping(int argc, char *argv[]) {
return 2;
}

if (opts.ver == IP_VER6 && opts.src_set) {
const char *em = "ping: -s is only supported for IPv4\n";
write_file(&fd, em, strlen(em));
close_file(&fd);
return 2;
}

if (opts.ver == IP_VER4 && opts.src_set) {
l3_ipv4_interface_t *l3 = l3_ipv4_find_by_ip(opts.src_ip);
if (!l3) {
Expand All @@ -250,7 +316,7 @@ int run_ping(int argc, char *argv[]) {

int rc = 0;
if (opts.ver == IP_VER4) rc = ping_v4(&fd, &opts);
else if (opts.ver == IP_VER6) rc = 3; //unimplemented
else if (opts.ver == IP_VER6) rc = ping_v6(&fd, &opts);
else { help(&fd); rc = 2; }

close_file(&fd);
Expand Down
58 changes: 58 additions & 0 deletions kernel/bin/shutdown.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "shutdown.h"

#include "kernel_processes/kprocess_loader.h"
#include "filesystem/filesystem.h"
#include "process/scheduler.h"
#include "std/string.h"
#include "hw/power.h"
#include "syscalls/syscalls.h"

int run_shutdown(int argc, char* argv[]){
const char *u = "usage: shutdown [-r|-p]\n -r reboot\n -p power off\n";


uint16_t pid = get_current_proc_pid();
string p = string_format("/proc/%i/out", pid);
file out;
FS_RESULT r = open_file(p.data, &out);
free_sized(p.data, p.mem_length);

if (r != FS_RESULT_SUCCESS){
return 2;
}
if (argc <= 0){
write_file(&out, u,strlen(u));
return 0;
}

int mode = -1;

for (int i = 0; i < argc; ++i){
const char *a = argv[i];
if (!a || a[0] == 0) continue;

if (strcmp(a, "-r") == 0) mode = SHUTDOWN_REBOOT;
else if (strcmp(a, "-p") == 0) mode = SHUTDOWN_POWEROFF;
else{
write_file(&out, u,strlen(u));
msleep(100);
close_file(&out);
return 2;
}
}

if (mode == -1){
write_file(&out, u,strlen(u));
msleep(100);
close_file(&out);
return 2;
}

if (mode == SHUTDOWN_REBOOT) write_file(&out, "Rebooting...\n", 13);
else write_file(&out, "Powering off...\n", 16);

msleep(100);
close_file(&out);
hw_shutdown(mode);
return 0;
}
3 changes: 3 additions & 0 deletions kernel/bin/shutdown.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

int run_shutdown(int argc, char* argv[]);
Loading