Network commands port to userspace

This commit is contained in:
boreddevnl 2026-02-27 23:24:43 +01:00
parent 304c2e1383
commit 8a6928b5c9
22 changed files with 680 additions and 69 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,33 +0,0 @@
src/kernel/wm.c: In function 'wm_handle_click':
src/kernel/wm.c:1491:29: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
1491 | if (col < 0) col = 0; if (row < 0) row = 0;
| ^~
src/kernel/wm.c:1491:51: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
1491 | if (col < 0) col = 0; if (row < 0) row = 0;
| ^~
src/kernel/wm.c: In function 'wm_handle_mouse':
src/kernel/wm.c:1884:17: error: implicit declaration of function 'cli_cmd_shutdown' [-Wimplicit-function-declaration]
1884 | cli_cmd_shutdown(NULL);
| ^~~~~~~~~~~~~~~~
src/kernel/wm.c:1886:17: error: implicit declaration of function 'cli_cmd_reboot' [-Wimplicit-function-declaration]
1886 | cli_cmd_reboot(NULL);
| ^~~~~~~~~~~~~~
src/kernel/wm.c:2083:41: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
2083 | if (col < 0) col = 0; if (row < 0) row = 0;
| ^~
src/kernel/wm.c:2083:63: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
2083 | if (col < 0) col = 0; if (row < 0) row = 0;
| ^~
src/kernel/wm.c: At top level:
src/kernel/wm.c:1057:13: warning: 'erase_cursor' defined but not used [-Wunused-function]
1057 | static void erase_cursor(int x, int y) {
| ^~~~~~~~~~~~
src/kernel/wm.c:976:13: warning: 'draw_dock_editor' defined but not used [-Wunused-function]
976 | static void draw_dock_editor(int x, int y) {
| ^~~~~~~~~~~~~~~~
src/kernel/wm.c:82:13: warning: 'cursor_visible' defined but not used [-Wunused-variable]
82 | static bool cursor_visible = true;
| ^~~~~~~~~~~~~~
src/kernel/wm.c:79:12: warning: 'desktop_refresh_timer' defined but not used [-Wunused-variable]
79 | static int desktop_refresh_timer = 0;
| ^~~~~~~~~~~~~~~~~~~~~

View file

@ -89,4 +89,62 @@ void cli_cmd_ping(char *args) {
}
}
is_pinging = false;
}
// Syscall version of ping for userland - returns success/failure
int cli_cmd_ping_syscall(ipv4_address_t *dest) {
if (!dest) return -1;
// Check if network is initialized
if (!network_is_initialized()) {
return -2; // Network not initialized
}
ipv4_address_t dest_ip = *dest;
is_pinging = true;
const int payload_size = 8;
uint8_t packet[sizeof(icmp_header_t) + payload_size];
icmp_header_t *icmp = (icmp_header_t *)packet;
int success_count = 0;
for (int i = 0; i < 4; i++) {
current_ping_id = ++ping_id_counter;
icmp->type = 8; // Echo Request
icmp->code = 0;
icmp->id = htons(current_ping_id);
icmp->sequence = htons(i + 1);
icmp->checksum = 0;
// Fill payload
for (int j = 0; j < payload_size; j++) {
packet[sizeof(icmp_header_t) + j] = (uint8_t)('a' + (j % 26));
}
icmp->checksum = net_checksum(packet, sizeof(packet));
ping_reply_received = false;
ip_send_packet(dest_ip, IP_PROTO_ICMP, packet, sizeof(packet));
uint32_t start_ticks = wm_get_ticks();
while (!ping_reply_received && (wm_get_ticks() - start_ticks) < 180) { // 3 seconds timeout
network_process_frames();
}
if (ping_reply_received) {
success_count++;
}
if (i < 3) {
// Wait a bit before next ping
uint32_t wait_start = wm_get_ticks();
while ((wm_get_ticks() - wait_start) < 60) {
network_process_frames();
}
}
}
is_pinging = false;
// Return number of successful replies
return success_count;
}

10
src/kernel/icmp.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef ICMP_H
#define ICMP_H
#include <stdint.h>
#include "network.h"
void icmp_handle_packet(ipv4_address_t src, void *data, uint16_t len);
int cli_cmd_ping_syscall(ipv4_address_t *dest);
#endif

View file

@ -46,13 +46,6 @@ static volatile struct limine_request *const requests_start_marker[] = {
NULL
};
__attribute__((used, section(".requests")))
static volatile struct limine_stack_size_request stack_size_request = {
.id = LIMINE_STACK_SIZE_REQUEST,
.revision = 0,
.stack_size = 1024 * 1024 // 1MB stack
};
__attribute__((used, section(".requests_end")))
static volatile struct limine_request *const requests_end_marker[] = {
NULL

View file

@ -31,6 +31,8 @@ void create_man_entries(void) {
fat32_mkdir("A:/Library");
fat32_mkdir("A:/Library/man");
write_man_file("ping", "PING - Send ICMP echo requests\n\nUsage: ping <ip>\n\nSends ICMP echo requests to the specified IP address and displays the response times.");
write_man_file("net", "NET - Network utilities\n\nUsage: net init\nnet info\nnet ipset >ip<\nnet udpsend >ip< >port< >message< net ping >ip< net help\n\nA collection of network-related commands.");
write_man_file("ls", "LS - List directory contents\n\nUsage: ls [path]\n\nLists files and directories in the current or specified directory.");
write_man_file("cat", "CAT - Concatenate and display file contents\n\nUsage: cat <filename>\n\nDisplays the text content of the specified file.");
write_man_file("man", "MAN - Display manual pages\n\nUsage: man <command>\n\nDisplays help information for the specified command.");

View file

@ -51,8 +51,8 @@ void process_create(void* entry_point, bool is_user) {
if (!new_proc->pml4_phys) return;
// 2. Allocate aligned stack
void* stack = kmalloc_aligned(524288, 4096); // 512KB for kernel threads
void* kernel_stack = kmalloc_aligned(126976, 16384); // 128KB for ringswitch
void* stack = kmalloc_aligned(4096, 4096);
void* kernel_stack = kmalloc_aligned(16384, 16384); // Needed for when user interrupts to Ring 0
if (is_user) {
// Map user stack to 0x800000
@ -66,7 +66,7 @@ void process_create(void* entry_point, bool is_user) {
// Build initial stack frame for iretq
// Stack grows down, start at top
uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 126976);
uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 16384);
*(--stack_ptr) = 0x1B; // SS (User Data)
*(--stack_ptr) = 0x800000 + 4096; // RSP
@ -79,11 +79,11 @@ void process_create(void* entry_point, bool is_user) {
// Push 15 zeros for general purpose registers (r15 -> rax)
for (int i = 0; i < 15; i++) *(--stack_ptr) = 0;
new_proc->kernel_stack = (uint64_t)kernel_stack + 126976;
new_proc->kernel_stack = (uint64_t)kernel_stack + 16384;
new_proc->rsp = (uint64_t)stack_ptr;
} else {
// Kernel thread
uint64_t* stack_ptr = (uint64_t*)((uint64_t)stack + 524288);
uint64_t* stack_ptr = (uint64_t*)((uint64_t)stack + 4096);
*(--stack_ptr) = 0x10; // SS (Kernel Data)
stack_ptr--;
*stack_ptr = (uint64_t)stack_ptr; // RSP
@ -134,18 +134,17 @@ process_t* process_create_elf(const char* filepath, const char* args_str) {
}
// 3. Allocate generic User stack and Kernel stack for interrupts
void* stack = kmalloc_aligned(2097152, 4096); // 2MB for user apps
void* kernel_stack = kmalloc_aligned(126976, 16384); // 128KB for interrupts
void* stack = kmalloc_aligned(65536, 4096);
void* kernel_stack = kmalloc_aligned(16384, 16384);
// Map User stack to 0x800000 (starting from 0x600000 for 2MB)
for (uint64_t i = 0; i < 512; i++) {
paging_map_page(new_proc->pml4_phys, 0x800000 - 2097152 + (i * 4096), v2p((uint64_t)stack + (i * 4096)), PT_PRESENT | PT_RW | PT_USER);
// Map User stack to 0x800000 (starting from 0x7F0000 for 64KB)
for (uint64_t i = 0; i < 16; i++) {
paging_map_page(new_proc->pml4_phys, 0x800000 - 65536 + (i * 4096), v2p((uint64_t)stack + (i * 4096)), PT_PRESENT | PT_RW | PT_USER);
}
// Parse arguments and push them to the user stack
// We'll place the strings at the very high end of the user stack
int argc = 1;
char *args_buf = (char *)stack + 2097152;
char *args_buf = (char *)stack + 65536;
uint64_t user_args_buf = 0x800000;
// Copy filepath as argv[0]
@ -197,7 +196,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str) {
// Align stack to 8 bytes before pushing argv array
uint64_t current_user_sp = user_args_buf;
current_user_sp &= ~7ULL;
args_buf = (char *)((uint64_t)stack + (current_user_sp - (0x800000 - 2097152)));
args_buf = (char *)((uint64_t)stack + (current_user_sp - (0x800000 - 65536)));
// Push argv array
int argv_size = (argc + 1) * sizeof(uint64_t);
@ -215,7 +214,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str) {
current_user_sp &= ~15ULL;
// 4. Build Stack Frame for context switch via IRETQ
uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 126976);
uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 16384);
*(--stack_ptr) = 0x1B; // SS (User Mode Data)
*(--stack_ptr) = current_user_sp; // RSP (Updated user stack pointer)
*(--stack_ptr) = 0x202; // RFLAGS (Interrupts Enabled)

View file

@ -10,6 +10,8 @@
#include "io.h"
#include "pci.h"
#include "kutils.h"
#include "network.h"
#include "icmp.h"
// Read MSR
static inline uint64_t rdmsr(uint32_t msr) {
@ -671,6 +673,54 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u
return 0;
}
return -1;
} else if (cmd == 18) { // SYSTEM_CMD_NETWORK_DHCP
return network_dhcp_acquire();
} else if (cmd == 19) { // SYSTEM_CMD_NETWORK_GET_MAC
mac_address_t *mac = (mac_address_t *)arg2;
if (!mac) return -1;
return network_get_mac_address(mac);
} else if (cmd == 20) { // SYSTEM_CMD_NETWORK_GET_IP
ipv4_address_t *ip = (ipv4_address_t *)arg2;
if (!ip) return -1;
return network_get_ipv4_address(ip);
} else if (cmd == 21) { // SYSTEM_CMD_NETWORK_SET_IP
ipv4_address_t *ip = (ipv4_address_t *)arg2;
if (!ip) return -1;
return network_set_ipv4_address(ip);
} else if (cmd == 22) { // SYSTEM_CMD_UDP_SEND
ipv4_address_t *dest_ip = (ipv4_address_t *)arg2;
uint32_t ports = (uint32_t)arg3; // dest_port in lower 16, src_port in upper 16
uint16_t dest_port = ports & 0xFFFF;
uint16_t src_port = (ports >> 16) & 0xFFFF;
const void *data = (const void *)arg4;
size_t data_len = (size_t)arg5;
if (!dest_ip || !data) return -1;
return udp_send_packet(dest_ip, dest_port, src_port, data, data_len);
} else if (cmd == 23) { // SYSTEM_CMD_NETWORK_GET_STATS
int stat_type = (int)arg2;
switch (stat_type) {
case 0: return network_get_frames_received();
case 1: return network_get_udp_packets_received();
case 2: return network_get_udp_callbacks_called();
case 3: return network_get_e1000_receive_calls();
case 4: return network_get_e1000_receive_empty();
case 5: return network_get_process_calls();
default: return -1;
}
} else if (cmd == 24) { // SYSTEM_CMD_NETWORK_GET_GATEWAY
ipv4_address_t *ip = (ipv4_address_t *)arg2;
if (!ip) return -1;
return network_get_gateway_ip(ip);
} else if (cmd == 25) { // SYSTEM_CMD_NETWORK_GET_DNS
ipv4_address_t *ip = (ipv4_address_t *)arg2;
if (!ip) return -1;
return network_get_dns_ip(ip);
} else if (cmd == 26) { // SYSTEM_CMD_ICMP_PING
ipv4_address_t *dest_ip = (ipv4_address_t *)arg2;
if (!dest_ip) return -1;
return cli_cmd_ping_syscall(dest_ip);
} else if (cmd == 27) { // SYSTEM_CMD_NETWORK_IS_INIT
return network_is_initialized() ? 1 : 0;
}
return -1;
}

View file

@ -191,17 +191,13 @@ static void calculator_click(int x, int y) {
if (calc_decimal_divisor > 10) {
calc_decimal_divisor /= 10;
long long unit = SCALE / calc_decimal_divisor;
// This removes the last decimal digit
calc_curr = (calc_curr / (unit * 10)) * (unit * 10);
} else {
// Backspace on the dot itself or first decimal
calc_decimal_mode = false;
calc_decimal_divisor = 10;
// Ensure the fractional part is cleared
calc_curr = (calc_curr / SCALE) * SCALE;
}
} else {
// Integer backspace: remove last digit of integer part
calc_curr = (calc_curr / SCALE / 10) * SCALE;
}
}
@ -240,11 +236,9 @@ int main(void) {
calc_new_entry = true;
update_display();
// First paint
calculator_paint();
ui_mark_dirty(win_calculator, 0, 0, 180, 230);
// Check events from Kernel User Interface queue
gui_event_t ev;
while (1) {
if (ui_get_event(win_calculator, &ev)) {

View file

@ -3,6 +3,6 @@
int main(int argc, char **argv) {
(void)argc; (void)argv;
sys_system(10, 0, 0, 0, 0); // SYSTEM_CMD_CLEAR_SCREEN
sys_system(10, 0, 0, 0, 0);
return 0;
}

View file

@ -4,8 +4,6 @@
int main(int argc, char **argv) {
char *msg = (char*)"Bored!";
if (argc > 1) {
// Simple concatenation of args for now
// For simplicity in this demo, just use the first arg
msg = argv[1];
}

View file

@ -3,7 +3,7 @@
int main(int argc, char **argv) {
(void)argc; (void)argv;
printf("BoredOS CLI Help (Userspace)\n");
printf("BoredOS CLI Help\n");
printf("---------------------------\n");
printf("ls [path] - List directory contents\n");
printf("cd <path> - Change current directory (built-in)\n");
@ -27,6 +27,6 @@ int main(int argc, char **argv) {
printf("man <cmd> - Show manual page\n");
printf("clear - Clear the screen\n");
printf("exit - Exit the terminal\n");
printf("\nHint: Use Ctrl+C to force quit any running .elf app.\n");
printf("\nHint: Use Ctrl+C to force quit any running application.\n");
return 0;
}

View file

@ -105,7 +105,7 @@ uint32_t sys_size(int fd) {
return (uint32_t)syscall2(SYS_FS, FS_CMD_SIZE, (uint64_t)fd);
}
int sys_list(const char *path, struct FAT32_FileInfo *entries, int max_entries) {
int sys_list(const char *path, FAT32_FileInfo *entries, int max_entries) {
return (int)syscall4(SYS_FS, FS_CMD_LIST, (uint64_t)path, (uint64_t)entries, (uint64_t)max_entries);
}
@ -133,3 +133,49 @@ void sys_kill(int pid) {
syscall1(SYS_KILL, (uint64_t)pid);
}
// Network API implementations
int sys_network_init(void) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_INIT, 0);
}
int sys_network_dhcp_acquire(void) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_DHCP, 0);
}
int sys_network_get_mac(net_mac_address_t *mac) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_MAC, (uint64_t)mac);
}
int sys_network_get_ip(net_ipv4_address_t *ip) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_IP, (uint64_t)ip);
}
int sys_network_set_ip(const net_ipv4_address_t *ip) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_SET_IP, (uint64_t)ip);
}
int sys_network_get_stat(int stat_type) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_STATS, (uint64_t)stat_type);
}
int sys_network_get_gateway(net_ipv4_address_t *ip) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_GATEWAY, (uint64_t)ip);
}
int sys_network_get_dns(net_ipv4_address_t *ip) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_DNS, (uint64_t)ip);
}
int sys_udp_send(const net_ipv4_address_t *dest_ip, uint16_t dest_port, uint16_t src_port, const void *data, size_t data_len) {
uint32_t ports = (dest_port & 0xFFFF) | ((src_port & 0xFFFF) << 16);
return (int)syscall5(SYS_SYSTEM, SYSTEM_CMD_UDP_SEND, (uint64_t)dest_ip, (uint64_t)ports, (uint64_t)data, (uint64_t)data_len);
}
int sys_icmp_ping(const net_ipv4_address_t *dest_ip) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_ICMP_PING, (uint64_t)dest_ip);
}
int sys_network_is_initialized(void) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_IS_INIT, 0);
}

View file

@ -2,6 +2,7 @@
#define SYSCALL_H
#include <stdint.h>
#include <stddef.h>
// Standard syscalls available from Kernel mode
#define SYS_EXIT 0
@ -27,6 +28,35 @@
#define FS_CMD_GETCWD 12
#define FS_CMD_CHDIR 13
// System Commands (via SYS_SYSTEM)
#define SYSTEM_CMD_SET_BG_COLOR 1
#define SYSTEM_CMD_SET_BG_PATTERN 2
#define SYSTEM_CMD_SET_WALLPAPER 3
#define SYSTEM_CMD_SET_DESKTOP_PROP 4
#define SYSTEM_CMD_SET_MOUSE_SPEED 5
#define SYSTEM_CMD_NETWORK_INIT 6
#define SYSTEM_CMD_GET_DESKTOP_PROP 7
#define SYSTEM_CMD_GET_MOUSE_SPEED 8
#define SYSTEM_CMD_GET_WALLPAPER_THUMB 9
#define SYSTEM_CMD_CLEAR_SCREEN 10
#define SYSTEM_CMD_RTC_GET 11
#define SYSTEM_CMD_REBOOT 12
#define SYSTEM_CMD_SHUTDOWN 13
#define SYSTEM_CMD_BEEP 14
#define SYSTEM_CMD_MEMINFO 15
#define SYSTEM_CMD_UPTIME 16
#define SYSTEM_CMD_PCI_LIST 17
#define SYSTEM_CMD_NETWORK_DHCP 18
#define SYSTEM_CMD_NETWORK_GET_MAC 19
#define SYSTEM_CMD_NETWORK_GET_IP 20
#define SYSTEM_CMD_NETWORK_SET_IP 21
#define SYSTEM_CMD_UDP_SEND 22
#define SYSTEM_CMD_NETWORK_GET_STATS 23
#define SYSTEM_CMD_NETWORK_GET_GATEWAY 24
#define SYSTEM_CMD_NETWORK_GET_DNS 25
#define SYSTEM_CMD_ICMP_PING 26
#define SYSTEM_CMD_NETWORK_IS_INIT 27
// Internal assembly entry into Ring 0
extern uint64_t syscall0(uint64_t sys_num);
extern uint64_t syscall1(uint64_t sys_num, uint64_t arg1);
@ -67,4 +97,20 @@ typedef struct {
int sys_list(const char *path, FAT32_FileInfo *entries, int max_entries);
// Network API
typedef struct { uint8_t bytes[6]; } net_mac_address_t;
typedef struct { uint8_t bytes[4]; } net_ipv4_address_t;
int sys_network_init(void);
int sys_network_dhcp_acquire(void);
int sys_network_get_mac(net_mac_address_t *mac);
int sys_network_get_ip(net_ipv4_address_t *ip);
int sys_network_set_ip(const net_ipv4_address_t *ip);
int sys_network_get_stat(int stat_type);
int sys_network_get_gateway(net_ipv4_address_t *ip);
int sys_network_get_dns(net_ipv4_address_t *ip);
int sys_udp_send(const net_ipv4_address_t *dest_ip, uint16_t dest_port, uint16_t src_port, const void *data, size_t data_len);
int sys_icmp_ping(const net_ipv4_address_t *dest_ip);
int sys_network_is_initialized(void);
#endif

View file

@ -7,7 +7,6 @@ int main(int argc, char **argv) {
return 1;
}
// Simplification: use cp then rm
int fd_in = sys_open(argv[1], "r");
if (fd_in < 0) {
printf("Error: Cannot open source %s\n", argv[1]);

376
src/kernel/userland/net.c Normal file
View file

@ -0,0 +1,376 @@
#include <stdlib.h>
#include <syscall.h>
// Helper function to print a MAC address
static void print_mac(const net_mac_address_t* mac) {
char buf[64];
int p = 0;
for (int i = 0; i < 6; i++) {
int v = mac->bytes[i];
int hi = (v >> 4) & 0xF;
int lo = v & 0xF;
buf[p++] = (hi < 10) ? ('0' + hi) : ('A' + (hi - 10));
buf[p++] = (lo < 10) ? ('0' + lo) : ('A' + (lo - 10));
if (i < 5) buf[p++] = ':';
}
buf[p] = 0;
printf("%s", buf);
}
// Helper to parse integer from string
static int string_to_int(const char *str) {
int result = 0;
int sign = 1;
if (*str == '-') {
sign = -1;
str++;
}
while (*str >= '0' && *str <= '9') {
result = result * 10 + (*str - '0');
str++;
}
return result * sign;
}
// Helper to get string length
static int string_length(const char *str) {
int len = 0;
while (str[len]) len++;
return len;
}
// Command: netinit - Initialize network and acquire DHCP
static void cmd_netinit(void) {
int r = sys_network_init();
if (r == 0) {
printf("Network initialized\n");
int d = sys_network_dhcp_acquire();
if (d == 0) {
printf("DHCP acquired\n");
} else {
printf("DHCP failed\n");
}
} else {
printf("Network init failed\n");
}
}
// Command: netinfo - Display network information
static void cmd_netinfo(void) {
if (!sys_network_is_initialized()) {
printf("Error: Network not initialized. Run 'net init' first.\n");
return;
}
net_mac_address_t mac;
net_ipv4_address_t ip;
if (sys_network_get_mac(&mac) == 0) {
printf("MAC: ");
print_mac(&mac);
printf("\n");
}
if (sys_network_get_ip(&ip) == 0) {
printf("IP: ");
for (int i = 0; i < 4; i++) {
printf("%d", ip.bytes[i]);
if (i < 3) printf(".");
}
printf("\n");
}
printf("Frames: %d\n", sys_network_get_stat(0));
printf("UDP packets: %d\n", sys_network_get_stat(1));
printf("UDP callbacks: %d\n", sys_network_get_stat(2));
printf("E1000 receive calls: %d\n", sys_network_get_stat(3));
printf("E1000 receive empty: %d\n", sys_network_get_stat(4));
printf("Process calls: %d\n", sys_network_get_stat(5));
}
// Command: ipset - Set IP address manually
static void cmd_ipset(const char *args) {
if (!sys_network_is_initialized()) {
printf("Error: Network not initialized. Run 'net init' first.\n");
return;
}
if (!args || !*args) {
printf("Usage: NET IPSET a.b.c.d\n");
return;
}
net_ipv4_address_t ip = {{0, 0, 0, 0}};
int part = 0;
int val = 0;
int i = 0;
while (args[i]) {
char ch = args[i++];
if (ch >= '0' && ch <= '9') {
val = val * 10 + (ch - '0');
if (val > 255) {
printf("Invalid IP\n");
return;
}
} else if (ch == '.') {
if (part > 3) {
printf("Invalid IP\n");
return;
}
ip.bytes[part++] = (uint8_t)val;
val = 0;
} else {
printf("Invalid IP\n");
return;
}
}
if (part != 3) {
printf("Invalid IP\n");
return;
}
ip.bytes[3] = (uint8_t)val;
if (sys_network_set_ip(&ip) == 0) {
printf("IP set\n");
} else {
printf("IP set failed\n");
}
}
// Command: udpsend - Send UDP packet
static void cmd_udpsend(const char *args) {
if (!sys_network_is_initialized()) {
printf("Error: Network not initialized. Run 'net init' first.\n");
return;
}
if (!args || !*args) {
printf("Usage: NET UDPSEND ip port data\n");
return;
}
// Parse IP address
char ipstr[32];
int pos = 0;
while (args[pos] && args[pos] != ' ') {
ipstr[pos] = args[pos];
pos++;
}
ipstr[pos] = 0;
while (args[pos] == ' ') pos++;
// Parse port
char portstr[16];
int p = 0;
while (args[pos] && args[pos] != ' ') {
portstr[p++] = args[pos++];
}
portstr[p] = 0;
while (args[pos] == ' ') pos++;
// Get data
const char *datastr = args + pos;
// Parse IP
net_ipv4_address_t ip = {{0, 0, 0, 0}};
int idx = 0;
int val = 0;
int j = 0;
while (ipstr[j]) {
char ch = ipstr[j++];
if (ch >= '0' && ch <= '9') {
val = val * 10 + (ch - '0');
if (val > 255) {
printf("Invalid IP\n");
return;
}
} else if (ch == '.') {
if (idx > 3) {
printf("Invalid IP\n");
return;
}
ip.bytes[idx++] = (uint8_t)val;
val = 0;
} else {
printf("Invalid IP\n");
return;
}
}
if (idx != 3) {
printf("Invalid IP\n");
return;
}
ip.bytes[3] = (uint8_t)val;
// Parse port
int port = 0;
int k = 0;
while (portstr[k]) {
char ch = portstr[k++];
if (ch < '0' || ch > '9') {
printf("Invalid port\n");
return;
}
port = port * 10 + (ch - '0');
}
if (port <= 0 || port > 65535) {
printf("Invalid port\n");
return;
}
int len = string_length(datastr);
if (len <= 0) {
printf("No data\n");
return;
}
int r = sys_udp_send(&ip, (uint16_t)port, 12345, datastr, (size_t)len);
if (r == 0) {
printf("Sent\n");
} else {
printf("Send failed\n");
}
}
// Command: ping - Send ICMP ping request
static void cmd_ping(const char *args) {
if (!sys_network_is_initialized()) {
printf("Error: Network not initialized. Run 'net init' first.\n");
return;
}
if (!args || !*args) {
printf("Usage: NET PING a.b.c.d\n");
return;
}
net_ipv4_address_t ip = {{0, 0, 0, 0}};
int idx = 0;
int val = 0;
int j = 0;
while (args[j]) {
char ch = args[j++];
if (ch >= '0' && ch <= '9') {
val = val * 10 + (ch - '0');
if (val > 255) {
printf("Invalid IP\n");
return;
}
} else if (ch == '.') {
if (idx > 3) {
printf("Invalid IP\n");
return;
}
ip.bytes[idx++] = (uint8_t)val;
val = 0;
} else if (ch == ' ' || ch == '\t') {
// Skip whitespace
while (args[j] == ' ' || args[j] == '\t') j++;
j--;
} else {
printf("Invalid IP\n");
return;
}
}
if (idx != 3) {
printf("Invalid IP\n");
return;
}
ip.bytes[3] = (uint8_t)val;
printf("Pinging ");
for (int i = 0; i < 4; i++) {
printf("%d", ip.bytes[i]);
if (i < 3) printf(".");
}
printf("...\n");
int result = sys_icmp_ping(&ip);
if (result == -2) {
printf("Error: Network not initialized. Run 'net init' first.\n");
} else if (result < 0) {
printf("Error: Failed to send ping request.\n");
} else {
printf("Ping complete: %d/%d replies received\n", result, 4);
}
}
// Command: help
static void cmd_help(void) {
printf("Network Commands:\n");
printf(" NET INIT - Initialize network and acquire DHCP\n");
printf(" NET INFO - Display network information\n");
printf(" NET IPSET a.b.c.d - Set IP address\n");
printf(" NET UDPSEND ip port data - Send UDP packet\n");
printf(" NET PING a.b.c.d - Send ICMP ping request\n");
printf(" NET HELP - Show this help\n");
}
int main(int argc, char **argv) {
if (argc < 2) {
cmd_help();
return 1;
}
const char *cmd = argv[1];
// Convert command to uppercase for easier comparison
char cmd_upper[32];
int i = 0;
while (cmd[i] && i < 31) {
char c = cmd[i];
cmd_upper[i] = (c >= 'a' && c <= 'z') ? (c - 'a' + 'A') : c;
i++;
}
cmd_upper[i] = 0;
// Parse arguments if provided
const char *args = "";
if (argc > 2) {
args = argv[2];
}
if ((string_length(cmd_upper) == 4 &&
cmd_upper[0] == 'I' && cmd_upper[1] == 'N' && cmd_upper[2] == 'I' && cmd_upper[3] == 'T') ||
(string_length(cmd_upper) == 7 &&
cmd_upper[0] == 'N' && cmd_upper[1] == 'E' && cmd_upper[2] == 'T' &&
cmd_upper[3] == 'I' && cmd_upper[4] == 'N' && cmd_upper[5] == 'I' && cmd_upper[6] == 'T')) {
cmd_netinit();
} else if ((string_length(cmd_upper) == 4 &&
cmd_upper[0] == 'I' && cmd_upper[1] == 'N' && cmd_upper[2] == 'F' && cmd_upper[3] == 'O') ||
(string_length(cmd_upper) == 7 &&
cmd_upper[0] == 'N' && cmd_upper[1] == 'E' && cmd_upper[2] == 'T' &&
cmd_upper[3] == 'I' && cmd_upper[4] == 'N' && cmd_upper[5] == 'F' && cmd_upper[6] == 'O')) {
cmd_netinfo();
} else if (string_length(cmd_upper) == 5 &&
cmd_upper[0] == 'I' && cmd_upper[1] == 'P' && cmd_upper[2] == 'S' &&
cmd_upper[3] == 'E' && cmd_upper[4] == 'T') {
cmd_ipset(args);
} else if (string_length(cmd_upper) == 7 &&
cmd_upper[0] == 'U' && cmd_upper[1] == 'D' && cmd_upper[2] == 'P' &&
cmd_upper[3] == 'S' && cmd_upper[4] == 'E' && cmd_upper[5] == 'N' && cmd_upper[6] == 'D') {
cmd_udpsend(args);
} else if (string_length(cmd_upper) == 4 &&
cmd_upper[0] == 'P' && cmd_upper[1] == 'I' && cmd_upper[2] == 'N' && cmd_upper[3] == 'G') {
cmd_ping(args);
} else if (string_length(cmd_upper) == 4 &&
cmd_upper[0] == 'H' && cmd_upper[1] == 'E' && cmd_upper[2] == 'L' && cmd_upper[3] == 'P') {
cmd_help();
} else {
printf("Unknown command: %s\n", cmd);
cmd_help();
return 1;
}
return 0;
}

View file

@ -10,7 +10,7 @@ typedef struct {
int main(int argc, char **argv) {
(void)argc; (void)argv;
int count = sys_system(17, 0, 0, 0, 0); // Get count
int count = sys_system(17, 0, 0, 0, 0);
if (count < 0) {
printf("Error: Could not retrieve PCI device count.\n");
return 1;

View file

@ -0,0 +1,73 @@
#include <stdlib.h>
#include <syscall.h>
int main(int argc, char **argv) {
if (argc < 2) {
printf("Usage: ping a.b.c.d\n");
return 1;
}
if (!sys_network_is_initialized()) {
printf("Error: Network not initialized. Run 'net init' first.\n");
return 1;
}
const char *args = argv[1];
net_ipv4_address_t ip = {{0, 0, 0, 0}};
int idx = 0;
int val = 0;
int j = 0;
while (args[j]) {
char ch = args[j++];
if (ch >= '0' && ch <= '9') {
val = val * 10 + (ch - '0');
if (val > 255) {
printf("Invalid IP\n");
return 1;
}
} else if (ch == '.') {
if (idx > 3) {
printf("Invalid IP\n");
return 1;
}
ip.bytes[idx++] = (uint8_t)val;
val = 0;
} else if (ch == ' ' || ch == '\t') {
// Skip whitespace
while (args[j] == ' ' || args[j] == '\t') j++;
j--;
} else {
printf("Invalid IP\n");
return 1;
}
}
if (idx != 3) {
printf("Invalid IP\n");
return 1;
}
ip.bytes[3] = (uint8_t)val;
printf("Pinging ");
for (int i = 0; i < 4; i++) {
printf("%d", ip.bytes[i]);
if (i < 3) printf(".");
}
printf("...\n");
int result = sys_icmp_ping(&ip);
if (result == -2) {
printf("Error: Network not initialized. Run 'net init' first.\n");
return 1;
} else if (result < 0) {
printf("Error: Failed to send ping request.\n");
return 1;
}
printf("Ping complete: %d/%d replies received\n", result, 4);
return 0;
}