Skip to content

Commit db54513

Browse files
authored
Merge pull request #65 from CodeAnarchist/ipv6
major network update, added IPv6, refactor TCP stack and various minor improvements
2 parents 2a968dd + aa0682a commit db54513

153 files changed

Lines changed: 15747 additions & 2622 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,21 @@ The Raspberry Pi emulation has the following limitations:
7777

7878
## Networking
7979

80-
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.
81-
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.
82-
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.
80+
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.
81+
82+
The stack follows a layered design. At link level it handles basic neighbor resolution (ARP for IPv4 and NDP for IPv6).
83+
84+
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)
85+
86+
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
87+
88+
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.
89+
90+
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).
91+
92+
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.
93+
94+
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
95+
8396
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.
8497
An implementation of the server can be found at the [RedactedOS Firmware Server Repository](https://github.com/differrari/RedactedOS_firmware_server/tree/main)

kernel/bin/bin_mod.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "bin_mod.h"
22
#include "ping.h"
3+
#include "shutdown.h"
34
#include "tracert.h"
45
#include "monitor_processes.h"
56
#include "kernel_processes/kprocess_loader.h"
@@ -22,6 +23,7 @@ typedef struct open_bin_ref {
2223

2324
open_bin_ref available_cmds[] = {
2425
{ "ping", run_ping },
26+
{ "shutdown", run_shutdown },
2527
{ "tracert", run_tracert },
2628
{ "monitor", monitor_procs },
2729
};

kernel/bin/ping.c

Lines changed: 119 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
#include "syscalls/syscalls.h"
1111
#include "networking/internet_layer/ipv4.h"
1212
#include "networking/internet_layer/ipv4_route.h"
13-
#include "networking/application_layer/dns.h"
13+
#include "networking/application_layer/dns/dns.h"
1414
#include "networking/internet_layer/ipv4_utils.h"
15+
#include "networking/internet_layer/ipv6_utils.h"
16+
#include "networking/internet_layer/icmpv6.h"
1517

1618
typedef struct {
1719
ip_version_t ver;
@@ -75,6 +77,23 @@ static bool parse_args(int argc, char *argv[], ping_opts_t *o) {
7577
return true;
7678
}
7779

80+
static const char *status_to_msg(uint8_t st) {
81+
switch (st) {
82+
case PING_TIMEOUT: return "Request timed out.";
83+
case PING_NET_UNREACH: return "Destination Net Unreachable.";
84+
case PING_HOST_UNREACH: return "Destination Host Unreachable.";
85+
case PING_PROTO_UNREACH: return "Protocol Unreachable.";
86+
case PING_PORT_UNREACH: return "Port Unreachable.";
87+
case PING_FRAG_NEEDED: return "Fragmentation Needed.";
88+
case PING_SRC_ROUTE_FAILED: return "Source Route Failed.";
89+
case PING_ADMIN_PROHIBITED: return "Administratively Prohibited.";
90+
case PING_TTL_EXPIRED: return "Time To Live exceeded.";
91+
case PING_PARAM_PROBLEM: return "Parameter Problem.";
92+
case PING_REDIRECT: return "Redirect received.";
93+
default: return "No reply (unknown error).";
94+
}
95+
}
96+
7897
static int ping_v4(file *fd, const ping_opts_t *o) {
7998
const char *host = o->host;
8099

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

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

111-
int8_t bound_index = -1;
112129
ipv4_tx_opts_t txo = {0};
113130
const ipv4_tx_opts_t *txop = NULL;
114131
if (o->src_set) {
115132
l3_ipv4_interface_t *l3 = l3_ipv4_find_by_ip(o->src_ip);
116-
//kprintf("%d", l3);
117133
if (!l3) {
118134
const char *em = "ping: invalid source (no local ip match)\n";
119135
write_file(fd, em, strlen_max(em, STRING_MAX_LEN));
120136
return 2;
121137
}
122-
123-
bound_index = (int8_t)l3->l3_id;
124-
txo.index = (uint8_t)bound_index;
125-
txo.scope = IPV4_TX_BOUND_L3;
138+
txo.index = (uint8_t)l3->l3_id;
139+
txo.scope = IP_TX_BOUND_L3;
126140
txop = &txo;
127-
char ssrc[16];
128-
ipv4_to_string(o->src_ip, ssrc);
129141
}
130142

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

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

138150
if (ok) {
139151
++received;
@@ -146,46 +158,93 @@ static int ping_v4(file *fd, const ping_opts_t *o) {
146158
write_file(fd, "\n", 1);
147159
free_sized(ln.data, ln.mem_length);
148160
} else {
149-
const char *msg = NULL;
150-
if (res.status == PING_TIMEOUT) msg = "Request timed out.";
151-
else {
152-
switch (res.status) {
153-
case PING_NET_UNREACH:
154-
msg = "Destination Net Unreachable.";
155-
break;
156-
case PING_HOST_UNREACH:
157-
msg = "Destination Host Unreachable.";
158-
break;
159-
case PING_PROTO_UNREACH:
160-
msg = "Protocol Unreachable.";
161-
break;
162-
case PING_PORT_UNREACH:
163-
msg = "Port Unreachable.";
164-
break;
165-
case PING_FRAG_NEEDED:
166-
msg = "Fragmentation Needed.";
167-
break;
168-
case PING_SRC_ROUTE_FAILED:
169-
msg = "Source Route Failed.";
170-
break;
171-
case PING_ADMIN_PROHIBITED:
172-
msg = "Administratively Prohibited.";
173-
break;
174-
case PING_TTL_EXPIRED:
175-
msg = "Time To Live exceeded.";
176-
break;
177-
case PING_PARAM_PROBLEM:
178-
msg = "Parameter Problem.";
179-
break;
180-
case PING_REDIRECT:
181-
msg = "Redirect received.";
182-
break;
183-
default:
184-
msg = "No reply (unknown error).";
185-
break;
186-
}
187-
}
188-
write_file(fd, msg, strlen_max(msg, STRING_MAX_LEN));
161+
const char *msg = status_to_msg(res.status);
162+
write_file(fd, msg, strlen(msg));
163+
write_file(fd, "\n", 1);
164+
}
165+
166+
if (i + 1 < o->count) msleep(o->interval_ms);
167+
}
168+
169+
write_file(fd, "\n", 1);
170+
171+
string h = string_format("--- %s ping statistics ---", host);
172+
write_file(fd, h.data, h.length);
173+
write_file(fd, "\n", 1);
174+
free_sized(h.data, h.mem_length);
175+
176+
uint32_t loss = (sent == 0) ? 0 : (uint32_t)((((uint64_t)(sent - received)) * 100) / sent);
177+
uint32_t total_time = (o->count > 0) ? (o->count - 1) * o->interval_ms : 0;
178+
179+
string s = string_format("%u packets transmitted, %u received, %u%% packet loss, time %ums", sent, received, loss, total_time);
180+
write_file(fd, s.data, s.length);
181+
write_file(fd, "\n", 1);
182+
free_sized(s.data, s.mem_length);
183+
184+
if (received > 0) {
185+
uint32_t avg = (uint32_t)(sum_ms / received);
186+
if (min_ms == UINT32_MAX) min_ms = avg;
187+
string r = string_format("rtt min/avg/max = %u/%u/%u ms", min_ms, avg, max_ms);
188+
write_file(fd, r.data, r.length);
189+
write_file(fd, "\n", 1);
190+
free_sized(r.data, r.mem_length);
191+
}
192+
193+
return (received > 0) ? 0 : 1;
194+
}
195+
196+
static int ping_v6(file *fd, const ping_opts_t *o) {
197+
const char *host = o->host;
198+
199+
uint8_t dst6[16] ={0};
200+
bool is_lit = ipv6_parse(host, dst6);
201+
if (!is_lit) {
202+
dns_result_t dr = dns_resolve_aaaa(host, dst6, DNS_USE_BOTH, o->timeout_ms);
203+
if (dr != DNS_OK) {
204+
string m = string_format("ping: dns lookup failed (%d) for '%s'",(int)dr, host);
205+
write_file(fd, m.data, m.length);
206+
write_file(fd, "\n", 1);
207+
free_sized(m.data, m.mem_length);
208+
return 2;
209+
}
210+
}
211+
212+
char ipstr[64];
213+
ipv6_to_string(dst6, ipstr, (int)sizeof(ipstr));
214+
215+
write_file(fd, "PING ", 5);
216+
write_file(fd, host, strlen(host));
217+
write_file(fd, " (", 2);
218+
write_file(fd, ipstr, strlen(ipstr));
219+
write_file(fd, ") with 32 bytes of data:", 25);
220+
write_file(fd, "\n", 1);
221+
222+
uint32_t sent = 0, received = 0, min_ms = UINT32_MAX, max_ms = 0;
223+
uint64_t sum_ms = 0;
224+
uint16_t id = (uint16_t)(get_current_proc_pid() & 0xFFFF);
225+
uint16_t seq_base = (uint16_t)(get_time() & 0xFFFF);
226+
227+
for (uint32_t i = 0; i < o->count; i++) {
228+
++sent;
229+
uint16_t seq = (uint16_t)(seq_base + i);
230+
231+
ping6_result_t res = {0};
232+
bool ok = icmpv6_ping(dst6, id, seq, o->timeout_ms, NULL, (uint8_t)o->ttl, &res);
233+
234+
if (ok) {
235+
++received;
236+
uint32_t rtt = res.rtt_ms;
237+
if (rtt < min_ms) min_ms = rtt;
238+
if (rtt > max_ms) max_ms = rtt;
239+
sum_ms += rtt;
240+
241+
string ln = string_format("Reply from %s: bytes=32 time=%ums", ipstr, (uint32_t)rtt);
242+
write_file(fd, ln.data, ln.length);
243+
write_file(fd, "\n", 1);
244+
free_sized(ln.data, ln.mem_length);
245+
} else {
246+
const char *msg = status_to_msg(res.status);
247+
write_file(fd, msg, strlen(msg));
189248
write_file(fd, "\n", 1);
190249
}
191250

@@ -234,6 +293,13 @@ int run_ping(int argc, char *argv[]) {
234293
return 2;
235294
}
236295

296+
if (opts.ver == IP_VER6 && opts.src_set) {
297+
const char *em = "ping: -s is only supported for IPv4\n";
298+
write_file(&fd, em, strlen(em));
299+
close_file(&fd);
300+
return 2;
301+
}
302+
237303
if (opts.ver == IP_VER4 && opts.src_set) {
238304
l3_ipv4_interface_t *l3 = l3_ipv4_find_by_ip(opts.src_ip);
239305
if (!l3) {
@@ -250,7 +316,7 @@ int run_ping(int argc, char *argv[]) {
250316

251317
int rc = 0;
252318
if (opts.ver == IP_VER4) rc = ping_v4(&fd, &opts);
253-
else if (opts.ver == IP_VER6) rc = 3; //unimplemented
319+
else if (opts.ver == IP_VER6) rc = ping_v6(&fd, &opts);
254320
else { help(&fd); rc = 2; }
255321

256322
close_file(&fd);

kernel/bin/shutdown.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include "shutdown.h"
2+
3+
#include "kernel_processes/kprocess_loader.h"
4+
#include "filesystem/filesystem.h"
5+
#include "process/scheduler.h"
6+
#include "std/string.h"
7+
#include "hw/power.h"
8+
#include "syscalls/syscalls.h"
9+
10+
int run_shutdown(int argc, char* argv[]){
11+
const char *u = "usage: shutdown [-r|-p]\n -r reboot\n -p power off\n";
12+
13+
14+
uint16_t pid = get_current_proc_pid();
15+
string p = string_format("/proc/%i/out", pid);
16+
file out;
17+
FS_RESULT r = open_file(p.data, &out);
18+
free_sized(p.data, p.mem_length);
19+
20+
if (r != FS_RESULT_SUCCESS){
21+
return 2;
22+
}
23+
if (argc <= 0){
24+
write_file(&out, u,strlen(u));
25+
return 0;
26+
}
27+
28+
int mode = -1;
29+
30+
for (int i = 0; i < argc; ++i){
31+
const char *a = argv[i];
32+
if (!a || a[0] == 0) continue;
33+
34+
if (strcmp(a, "-r") == 0) mode = SHUTDOWN_REBOOT;
35+
else if (strcmp(a, "-p") == 0) mode = SHUTDOWN_POWEROFF;
36+
else{
37+
write_file(&out, u,strlen(u));
38+
msleep(100);
39+
close_file(&out);
40+
return 2;
41+
}
42+
}
43+
44+
if (mode == -1){
45+
write_file(&out, u,strlen(u));
46+
msleep(100);
47+
close_file(&out);
48+
return 2;
49+
}
50+
51+
if (mode == SHUTDOWN_REBOOT) write_file(&out, "Rebooting...\n", 13);
52+
else write_file(&out, "Powering off...\n", 16);
53+
54+
msleep(100);
55+
close_file(&out);
56+
hw_shutdown(mode);
57+
return 0;
58+
}

kernel/bin/shutdown.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
int run_shutdown(int argc, char* argv[]);

0 commit comments

Comments
 (0)