mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-27 05:34:00 +00:00
外网通讯+TTY优化
This commit is contained in:
@@ -25,7 +25,17 @@ set(OBJCOPY_FOR_TARGET "llvm-objcopy" CACHE STRING "objcopy tool for limine conf
|
|||||||
set(OBJDUMP_FOR_TARGET "llvm-objdump" CACHE STRING "objdump tool for limine configure")
|
set(OBJDUMP_FOR_TARGET "llvm-objdump" CACHE STRING "objdump tool for limine configure")
|
||||||
set(READELF_FOR_TARGET "llvm-readelf" CACHE STRING "readelf tool for limine configure")
|
set(READELF_FOR_TARGET "llvm-readelf" CACHE STRING "readelf tool for limine configure")
|
||||||
|
|
||||||
set(QEMU_X86_64 "qemu-system-x86_64" CACHE STRING "QEMU executable")
|
set(QEMU_X86_64 "qemu-system-x86_64" CACHE STRING "QEMU executable")
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
set(_cleonos_qemu_kvm_default ON)
|
||||||
|
else()
|
||||||
|
set(_cleonos_qemu_kvm_default OFF)
|
||||||
|
endif()
|
||||||
|
set(CLEONOS_QEMU_ENABLE_KVM ${_cleonos_qemu_kvm_default} CACHE BOOL "Enable QEMU KVM acceleration for run/debug targets")
|
||||||
|
set(CLEONOS_QEMU_ACCEL_ARGS "")
|
||||||
|
if(CLEONOS_QEMU_ENABLE_KVM)
|
||||||
|
list(APPEND CLEONOS_QEMU_ACCEL_ARGS -enable-kvm -cpu host)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CLEONOS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/cleonos")
|
set(CLEONOS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/cleonos")
|
||||||
if(EXISTS "${CLEONOS_SOURCE_DIR}/CMakeLists.txt")
|
if(EXISTS "${CLEONOS_SOURCE_DIR}/CMakeLists.txt")
|
||||||
@@ -348,27 +358,27 @@ if(CLEONOS_ENABLE)
|
|||||||
add_custom_target(iso ALL DEPENDS "${ISO_IMAGE}")
|
add_custom_target(iso ALL DEPENDS "${ISO_IMAGE}")
|
||||||
add_dependencies(iso setup-tools setup-limine kernel ramdisk)
|
add_dependencies(iso setup-tools setup-limine kernel ramdisk)
|
||||||
|
|
||||||
add_custom_target(run
|
add_custom_target(run
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
"-DNO_COLOR=${NO_COLOR}"
|
"-DNO_COLOR=${NO_COLOR}"
|
||||||
"-DLOG_LEVEL=STEP"
|
"-DLOG_LEVEL=STEP"
|
||||||
"-DLOG_TEXT=launching qemu run"
|
"-DLOG_TEXT=launching qemu run"
|
||||||
-P "${CL_LOG_EMIT_SCRIPT}"
|
-P "${CL_LOG_EMIT_SCRIPT}"
|
||||||
COMMAND ${QEMU_X86_64} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -netdev "user,id=clksnet0" -device "e1000,netdev=clksnet0" -serial stdio
|
COMMAND ${QEMU_X86_64} ${CLEONOS_QEMU_ACCEL_ARGS} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -netdev "user,id=clksnet0" -device "e1000,netdev=clksnet0" -serial stdio
|
||||||
DEPENDS iso disk-image
|
DEPENDS iso disk-image
|
||||||
USES_TERMINAL
|
USES_TERMINAL
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(debug
|
add_custom_target(debug
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
"-DNO_COLOR=${NO_COLOR}"
|
"-DNO_COLOR=${NO_COLOR}"
|
||||||
"-DLOG_LEVEL=STEP"
|
"-DLOG_LEVEL=STEP"
|
||||||
"-DLOG_TEXT=launching qemu debug (-s -S)"
|
"-DLOG_TEXT=launching qemu debug (-s -S)"
|
||||||
-P "${CL_LOG_EMIT_SCRIPT}"
|
-P "${CL_LOG_EMIT_SCRIPT}"
|
||||||
COMMAND ${QEMU_X86_64} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -netdev "user,id=clksnet0" -device "e1000,netdev=clksnet0" -serial stdio -s -S
|
COMMAND ${QEMU_X86_64} ${CLEONOS_QEMU_ACCEL_ARGS} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -netdev "user,id=clksnet0" -device "e1000,netdev=clksnet0" -serial stdio -s -S
|
||||||
DEPENDS iso disk-image
|
DEPENDS iso disk-image
|
||||||
USES_TERMINAL
|
USES_TERMINAL
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
add_custom_target(clks-default ALL DEPENDS kernel)
|
add_custom_target(clks-default ALL DEPENDS kernel)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
3
Makefile
3
Makefile
@@ -236,6 +236,9 @@ help:
|
|||||||
> $(Q)echo " make run V=1"
|
> $(Q)echo " make run V=1"
|
||||||
> $(Q)echo " make run SHOW_COMMANDS=1"
|
> $(Q)echo " make run SHOW_COMMANDS=1"
|
||||||
> $(Q)echo " (includes CMake build internals: compiler/linker command lines)"
|
> $(Q)echo " (includes CMake build internals: compiler/linker command lines)"
|
||||||
|
> $(Q)echo "QEMU KVM toggle:"
|
||||||
|
> $(Q)echo " make run CMAKE_EXTRA_ARGS='-DCLEONOS_QEMU_ENABLE_KVM=ON' # force on"
|
||||||
|
> $(Q)echo " make run CMAKE_EXTRA_ARGS='-DCLEONOS_QEMU_ENABLE_KVM=OFF' # force off"
|
||||||
> $(Q)echo ""
|
> $(Q)echo ""
|
||||||
> $(Q)echo "Pass custom CMake cache args via:"
|
> $(Q)echo "Pass custom CMake cache args via:"
|
||||||
> $(Q)echo " make configure CMAKE_EXTRA_ARGS='-DLIMINE_SKIP_CONFIGURE=1 -DOBJCOPY_FOR_TARGET=objcopy'"
|
> $(Q)echo " make configure CMAKE_EXTRA_ARGS='-DLIMINE_SKIP_CONFIGURE=1 -DOBJCOPY_FOR_TARGET=objcopy'"
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ list(SORT DOOMGENERIC_DEP_SOURCES_ABS)
|
|||||||
|
|
||||||
set(USER_SHELL_COMMAND_APPS
|
set(USER_SHELL_COMMAND_APPS
|
||||||
help args ls cat grep head tail wc cut uniq sort pwd cd exec pid spawn wait sleep yield
|
help args ls cat grep head tail wc cut uniq sort pwd cd exec pid spawn wait sleep yield
|
||||||
ping
|
ping ifconfig nslookup
|
||||||
bg fg jobs kill ps top
|
bg fg jobs kill ps top
|
||||||
procstat sysstat
|
procstat sysstat
|
||||||
diskinfo mkfsfat32 mount partctl
|
diskinfo mkfsfat32 mount partctl
|
||||||
|
|||||||
@@ -32,9 +32,11 @@ static int ush_cmd_help(void) {
|
|||||||
ush_writeln(" diskinfo");
|
ush_writeln(" diskinfo");
|
||||||
ush_writeln(" mkfsfat32 [label]");
|
ush_writeln(" mkfsfat32 [label]");
|
||||||
ush_writeln(" mount [path] (default suggested: /temp/disk)");
|
ush_writeln(" mount [path] (default suggested: /temp/disk)");
|
||||||
ush_writeln(" partctl <subcommand> (mbr partition control: list/init-mbr/create/delete/set-boot)");
|
ush_writeln(" partctl <subcommand> (mbr partition control: list/init-mbr/create/delete/set-boot)");
|
||||||
ush_writeln(" ping <a.b.c.d> [count]");
|
ush_writeln(" ping <a.b.c.d> [count]");
|
||||||
ush_writeln(" pid");
|
ush_writeln(" ifconfig");
|
||||||
|
ush_writeln(" nslookup <domain>");
|
||||||
|
ush_writeln(" pid");
|
||||||
ush_writeln(" spawn <path|name> [args...] / bg <path|name> [args...]");
|
ush_writeln(" spawn <path|name> [args...] / bg <path|name> [args...]");
|
||||||
ush_writeln(" wait <pid> / fg [pid]");
|
ush_writeln(" wait <pid> / fg [pid]");
|
||||||
ush_writeln(" kill <pid> [signal]");
|
ush_writeln(" kill <pid> [signal]");
|
||||||
|
|||||||
101
cleonos/c/apps/ifconfig_main.c
Normal file
101
cleonos/c/apps/ifconfig_main.c
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#include "cmd_runtime.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static void ush_ifconfig_print_ipv4(u64 ipv4_be) {
|
||||||
|
unsigned int a = (unsigned int)((ipv4_be >> 24ULL) & 0xFFULL);
|
||||||
|
unsigned int b = (unsigned int)((ipv4_be >> 16ULL) & 0xFFULL);
|
||||||
|
unsigned int c = (unsigned int)((ipv4_be >> 8ULL) & 0xFFULL);
|
||||||
|
unsigned int d = (unsigned int)(ipv4_be & 0xFFULL);
|
||||||
|
|
||||||
|
(void)printf("%u.%u.%u.%u", a, b, c, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_cmd_ifconfig(const char *arg) {
|
||||||
|
u64 available;
|
||||||
|
u64 ip;
|
||||||
|
u64 netmask;
|
||||||
|
u64 gateway;
|
||||||
|
u64 dns;
|
||||||
|
|
||||||
|
if (arg != (const char *)0 && arg[0] != '\0') {
|
||||||
|
if (ush_streq(arg, "--help") != 0 || ush_streq(arg, "-h") != 0) {
|
||||||
|
(void)puts("usage: ifconfig");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
(void)puts("ifconfig: usage ifconfig");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
available = cleonos_sys_net_available();
|
||||||
|
if (available == 0ULL) {
|
||||||
|
(void)puts("ifconfig: network unavailable");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ip = cleonos_sys_net_ipv4_addr();
|
||||||
|
netmask = cleonos_sys_net_netmask();
|
||||||
|
gateway = cleonos_sys_net_gateway();
|
||||||
|
dns = cleonos_sys_net_dns_server();
|
||||||
|
|
||||||
|
(void)fputs("inet: ", 1);
|
||||||
|
ush_ifconfig_print_ipv4(ip);
|
||||||
|
(void)putchar('\n');
|
||||||
|
|
||||||
|
(void)fputs("netmask: ", 1);
|
||||||
|
ush_ifconfig_print_ipv4(netmask);
|
||||||
|
(void)putchar('\n');
|
||||||
|
|
||||||
|
(void)fputs("gateway: ", 1);
|
||||||
|
ush_ifconfig_print_ipv4(gateway);
|
||||||
|
(void)putchar('\n');
|
||||||
|
|
||||||
|
(void)fputs("dns: ", 1);
|
||||||
|
ush_ifconfig_print_ipv4(dns);
|
||||||
|
(void)putchar('\n');
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cleonos_app_main(void) {
|
||||||
|
ush_cmd_ctx ctx;
|
||||||
|
ush_cmd_ret ret;
|
||||||
|
ush_state sh;
|
||||||
|
char initial_cwd[USH_PATH_MAX];
|
||||||
|
int has_context = 0;
|
||||||
|
int success = 0;
|
||||||
|
const char *arg = "";
|
||||||
|
|
||||||
|
ush_zero(&ctx, (u64)sizeof(ctx));
|
||||||
|
ush_zero(&ret, (u64)sizeof(ret));
|
||||||
|
ush_init_state(&sh);
|
||||||
|
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
|
||||||
|
|
||||||
|
if (ush_command_ctx_read(&ctx) != 0) {
|
||||||
|
if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "ifconfig") != 0) {
|
||||||
|
has_context = 1;
|
||||||
|
arg = ctx.arg;
|
||||||
|
if (ctx.cwd[0] == '/') {
|
||||||
|
ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd);
|
||||||
|
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
success = ush_cmd_ifconfig(arg);
|
||||||
|
|
||||||
|
if (has_context != 0) {
|
||||||
|
if (ush_streq(sh.cwd, initial_cwd) == 0) {
|
||||||
|
ret.flags |= USH_CMD_RET_FLAG_CWD;
|
||||||
|
ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sh.exit_requested != 0) {
|
||||||
|
ret.flags |= USH_CMD_RET_FLAG_EXIT;
|
||||||
|
ret.exit_code = sh.exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)ush_command_ret_write(&ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (success != 0) ? 0 : 1;
|
||||||
|
}
|
||||||
353
cleonos/c/apps/nslookup_main.c
Normal file
353
cleonos/c/apps/nslookup_main.c
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
#include "cmd_runtime.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define USH_DNS_QUERY_MAX 512U
|
||||||
|
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
|
||||||
|
static u16 ush_dns_read_be16(const u8 *ptr) {
|
||||||
|
return (u16)(((u16)ptr[0] << 8U) | (u16)ptr[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_dns_write_be16(u8 *ptr, u16 value) {
|
||||||
|
ptr[0] = (u8)((value >> 8U) & 0xFFU);
|
||||||
|
ptr[1] = (u8)(value & 0xFFU);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_dns_print_ipv4_be(u64 ipv4_be) {
|
||||||
|
unsigned int a = (unsigned int)((ipv4_be >> 24ULL) & 0xFFULL);
|
||||||
|
unsigned int b = (unsigned int)((ipv4_be >> 16ULL) & 0xFFULL);
|
||||||
|
unsigned int c = (unsigned int)((ipv4_be >> 8ULL) & 0xFFULL);
|
||||||
|
unsigned int d = (unsigned int)(ipv4_be & 0xFFULL);
|
||||||
|
(void)printf("%u.%u.%u.%u", a, b, c, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_dns_encode_qname(const char *host, u8 *out, u64 out_cap, u64 *out_len) {
|
||||||
|
const char *p;
|
||||||
|
u64 at = 0ULL;
|
||||||
|
|
||||||
|
if (host == (const char *)0 || out == (u8 *)0 || out_len == (u64 *)0 || out_cap < 2ULL || host[0] == '\0') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = host;
|
||||||
|
while (*p != '\0') {
|
||||||
|
const char *dot = p;
|
||||||
|
u64 label_len;
|
||||||
|
u64 i;
|
||||||
|
|
||||||
|
while (*dot != '\0' && *dot != '.') {
|
||||||
|
dot++;
|
||||||
|
}
|
||||||
|
|
||||||
|
label_len = (u64)(dot - p);
|
||||||
|
if (label_len == 0ULL || label_len > 63ULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (at + 1ULL + label_len + 1ULL > out_cap) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[at++] = (u8)label_len;
|
||||||
|
for (i = 0ULL; i < label_len; i++) {
|
||||||
|
out[at++] = (u8)p[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*dot == '.') {
|
||||||
|
p = dot + 1;
|
||||||
|
} else {
|
||||||
|
p = dot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out[at++] = 0U;
|
||||||
|
*out_len = at;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_dns_skip_name(const u8 *msg, u64 msg_len, u64 *io_off) {
|
||||||
|
u64 pos;
|
||||||
|
u64 depth = 0ULL;
|
||||||
|
int jumped = 0;
|
||||||
|
|
||||||
|
if (msg == (const u8 *)0 || io_off == (u64 *)0 || *io_off >= msg_len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = *io_off;
|
||||||
|
while (depth < 32ULL) {
|
||||||
|
u8 len;
|
||||||
|
|
||||||
|
if (pos >= msg_len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = msg[pos];
|
||||||
|
if (len == 0U) {
|
||||||
|
if (jumped == 0) {
|
||||||
|
*io_off = pos + 1ULL;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((len & 0xC0U) == 0xC0U) {
|
||||||
|
u16 ptr;
|
||||||
|
|
||||||
|
if (pos + 1ULL >= msg_len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ptr = (u16)(((u16)(len & 0x3FU) << 8U) | (u16)msg[pos + 1ULL]);
|
||||||
|
if ((u64)ptr >= msg_len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jumped == 0) {
|
||||||
|
*io_off = pos + 2ULL;
|
||||||
|
jumped = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = (u64)ptr;
|
||||||
|
depth++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((len & 0xC0U) != 0U) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos + 1ULL + (u64)len > msg_len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += 1ULL + (u64)len;
|
||||||
|
if (jumped == 0) {
|
||||||
|
*io_off = pos;
|
||||||
|
}
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_dns_parse_response(const u8 *resp, u64 resp_len, u16 expected_id) {
|
||||||
|
u16 id;
|
||||||
|
u16 flags;
|
||||||
|
u16 qdcount;
|
||||||
|
u16 ancount;
|
||||||
|
u16 i;
|
||||||
|
u64 off = 12ULL;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
if (resp == (const u8 *)0 || resp_len < 12ULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = ush_dns_read_be16(&resp[0]);
|
||||||
|
if (id != expected_id) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = ush_dns_read_be16(&resp[2]);
|
||||||
|
qdcount = ush_dns_read_be16(&resp[4]);
|
||||||
|
ancount = ush_dns_read_be16(&resp[6]);
|
||||||
|
|
||||||
|
if ((flags & 0x8000U) == 0U) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & 0x000FU) != 0U) {
|
||||||
|
(void)printf("nslookup: server error rcode=%u\n", (unsigned int)(flags & 0x000FU));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0U; i < qdcount; i++) {
|
||||||
|
if (ush_dns_skip_name(resp, resp_len, &off) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (off + 4ULL > resp_len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
off += 4ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0U; i < ancount; i++) {
|
||||||
|
u16 type;
|
||||||
|
u16 klass;
|
||||||
|
u16 rdlen;
|
||||||
|
|
||||||
|
if (ush_dns_skip_name(resp, resp_len, &off) == 0) {
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
if (off + 10ULL > resp_len) {
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = ush_dns_read_be16(&resp[off + 0ULL]);
|
||||||
|
klass = ush_dns_read_be16(&resp[off + 2ULL]);
|
||||||
|
rdlen = ush_dns_read_be16(&resp[off + 8ULL]);
|
||||||
|
off += 10ULL;
|
||||||
|
|
||||||
|
if (off + (u64)rdlen > resp_len) {
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == 1U && klass == 1U && rdlen == 4U) {
|
||||||
|
u64 ip = ((u64)resp[off] << 24ULL) | ((u64)resp[off + 1ULL] << 16ULL) |
|
||||||
|
((u64)resp[off + 2ULL] << 8ULL) | (u64)resp[off + 3ULL];
|
||||||
|
ush_dns_print_ipv4_be(ip);
|
||||||
|
(void)putchar('\n');
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
|
||||||
|
off += (u64)rdlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_cmd_nslookup(const char *arg) {
|
||||||
|
u64 dns_server;
|
||||||
|
u8 query[USH_DNS_QUERY_MAX];
|
||||||
|
u8 answer[USH_DNS_QUERY_MAX];
|
||||||
|
u64 qname_len = 0ULL;
|
||||||
|
u64 query_len;
|
||||||
|
u16 txid;
|
||||||
|
u16 src_port;
|
||||||
|
cleonos_net_udp_send_req send_req;
|
||||||
|
int loops;
|
||||||
|
|
||||||
|
if (arg == (const char *)0 || arg[0] == '\0') {
|
||||||
|
(void)puts("nslookup: usage nslookup <domain>");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleonos_sys_net_available() == 0ULL) {
|
||||||
|
(void)puts("nslookup: network unavailable");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_server = cleonos_sys_net_dns_server();
|
||||||
|
if (dns_server == 0ULL) {
|
||||||
|
(void)puts("nslookup: dns server unavailable");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
txid = (u16)((cleonos_sys_timer_ticks() ^ 0xA5C3ULL) & 0xFFFFULL);
|
||||||
|
src_port = (u16)(40000U + (txid % 20000U));
|
||||||
|
|
||||||
|
(void)memset(query, 0, sizeof(query));
|
||||||
|
if (ush_dns_encode_qname(arg, query + 12ULL, (u64)sizeof(query) - 12ULL, &qname_len) == 0) {
|
||||||
|
(void)puts("nslookup: invalid domain");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ush_dns_write_be16(&query[0], txid);
|
||||||
|
ush_dns_write_be16(&query[2], 0x0100U);
|
||||||
|
ush_dns_write_be16(&query[4], 1U);
|
||||||
|
ush_dns_write_be16(&query[6], 0U);
|
||||||
|
ush_dns_write_be16(&query[8], 0U);
|
||||||
|
ush_dns_write_be16(&query[10], 0U);
|
||||||
|
|
||||||
|
query_len = 12ULL + qname_len;
|
||||||
|
if (query_len + 4ULL > (u64)sizeof(query)) {
|
||||||
|
(void)puts("nslookup: query too large");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ush_dns_write_be16(&query[query_len], 1U);
|
||||||
|
ush_dns_write_be16(&query[query_len + 2ULL], 1U);
|
||||||
|
query_len += 4ULL;
|
||||||
|
|
||||||
|
send_req.dst_ipv4_be = dns_server;
|
||||||
|
send_req.dst_port = 53ULL;
|
||||||
|
send_req.src_port = (u64)src_port;
|
||||||
|
send_req.payload_ptr = (u64)(usize)query;
|
||||||
|
send_req.payload_len = query_len;
|
||||||
|
|
||||||
|
if (cleonos_sys_net_udp_send(&send_req) != query_len) {
|
||||||
|
(void)puts("nslookup: send failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)fputs("Server: ", 1);
|
||||||
|
ush_dns_print_ipv4_be(dns_server);
|
||||||
|
(void)putchar('\n');
|
||||||
|
(void)fputs("Query: ", 1);
|
||||||
|
(void)puts(arg);
|
||||||
|
(void)puts("Answer:");
|
||||||
|
|
||||||
|
for (loops = 0; loops < 600; loops++) {
|
||||||
|
cleonos_net_udp_recv_req recv_req;
|
||||||
|
u64 got;
|
||||||
|
u64 src_ip = 0ULL;
|
||||||
|
u64 src_p = 0ULL;
|
||||||
|
u64 dst_p = 0ULL;
|
||||||
|
|
||||||
|
recv_req.out_payload_ptr = (u64)(usize)answer;
|
||||||
|
recv_req.payload_capacity = (u64)sizeof(answer);
|
||||||
|
recv_req.out_src_ipv4_ptr = (u64)(usize)&src_ip;
|
||||||
|
recv_req.out_src_port_ptr = (u64)(usize)&src_p;
|
||||||
|
recv_req.out_dst_port_ptr = (u64)(usize)&dst_p;
|
||||||
|
|
||||||
|
got = cleonos_sys_net_udp_recv(&recv_req);
|
||||||
|
if (got == 0ULL) {
|
||||||
|
(void)cleonos_sys_sleep_ticks(2ULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_p != 53ULL || src_ip != dns_server) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ush_dns_parse_response(answer, got, txid) > 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)puts("nslookup: timeout");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cleonos_app_main(void) {
|
||||||
|
ush_cmd_ctx ctx;
|
||||||
|
ush_cmd_ret ret;
|
||||||
|
ush_state sh;
|
||||||
|
char initial_cwd[USH_PATH_MAX];
|
||||||
|
int has_context = 0;
|
||||||
|
int success = 0;
|
||||||
|
const char *arg = "";
|
||||||
|
|
||||||
|
ush_zero(&ctx, (u64)sizeof(ctx));
|
||||||
|
ush_zero(&ret, (u64)sizeof(ret));
|
||||||
|
ush_init_state(&sh);
|
||||||
|
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
|
||||||
|
|
||||||
|
if (ush_command_ctx_read(&ctx) != 0) {
|
||||||
|
if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "nslookup") != 0) {
|
||||||
|
has_context = 1;
|
||||||
|
arg = ctx.arg;
|
||||||
|
if (ctx.cwd[0] == '/') {
|
||||||
|
ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd);
|
||||||
|
ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
success = ush_cmd_nslookup(arg);
|
||||||
|
|
||||||
|
if (has_context != 0) {
|
||||||
|
if (ush_streq(sh.cwd, initial_cwd) == 0) {
|
||||||
|
ret.flags |= USH_CMD_RET_FLAG_CWD;
|
||||||
|
ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sh.exit_requested != 0) {
|
||||||
|
ret.flags |= USH_CMD_RET_FLAG_EXIT;
|
||||||
|
ret.exit_code = sh.exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)ush_command_ret_write(&ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (success != 0) ? 0 : 1;
|
||||||
|
}
|
||||||
@@ -172,10 +172,13 @@ typedef struct cleonos_net_udp_recv_req {
|
|||||||
#define CLEONOS_SYSCALL_DISK_READ_SECTOR 93ULL
|
#define CLEONOS_SYSCALL_DISK_READ_SECTOR 93ULL
|
||||||
#define CLEONOS_SYSCALL_DISK_WRITE_SECTOR 94ULL
|
#define CLEONOS_SYSCALL_DISK_WRITE_SECTOR 94ULL
|
||||||
#define CLEONOS_SYSCALL_NET_AVAILABLE 95ULL
|
#define CLEONOS_SYSCALL_NET_AVAILABLE 95ULL
|
||||||
#define CLEONOS_SYSCALL_NET_IPV4_ADDR 96ULL
|
#define CLEONOS_SYSCALL_NET_IPV4_ADDR 96ULL
|
||||||
#define CLEONOS_SYSCALL_NET_PING 97ULL
|
#define CLEONOS_SYSCALL_NET_PING 97ULL
|
||||||
#define CLEONOS_SYSCALL_NET_UDP_SEND 98ULL
|
#define CLEONOS_SYSCALL_NET_UDP_SEND 98ULL
|
||||||
#define CLEONOS_SYSCALL_NET_UDP_RECV 99ULL
|
#define CLEONOS_SYSCALL_NET_UDP_RECV 99ULL
|
||||||
|
#define CLEONOS_SYSCALL_NET_NETMASK 100ULL
|
||||||
|
#define CLEONOS_SYSCALL_NET_GATEWAY 101ULL
|
||||||
|
#define CLEONOS_SYSCALL_NET_DNS_SERVER 102ULL
|
||||||
|
|
||||||
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
||||||
u64 cleonos_sys_log_write(const char *message, u64 length);
|
u64 cleonos_sys_log_write(const char *message, u64 length);
|
||||||
@@ -273,10 +276,13 @@ u64 cleonos_sys_disk_mounted(void);
|
|||||||
u64 cleonos_sys_disk_mount_path(char *out_path, u64 out_size);
|
u64 cleonos_sys_disk_mount_path(char *out_path, u64 out_size);
|
||||||
u64 cleonos_sys_disk_read_sector(u64 lba, void *out_sector);
|
u64 cleonos_sys_disk_read_sector(u64 lba, void *out_sector);
|
||||||
u64 cleonos_sys_disk_write_sector(u64 lba, const void *sector_data);
|
u64 cleonos_sys_disk_write_sector(u64 lba, const void *sector_data);
|
||||||
u64 cleonos_sys_net_available(void);
|
u64 cleonos_sys_net_available(void);
|
||||||
u64 cleonos_sys_net_ipv4_addr(void);
|
u64 cleonos_sys_net_ipv4_addr(void);
|
||||||
u64 cleonos_sys_net_ping(u64 dst_ipv4_be, u64 poll_budget);
|
u64 cleonos_sys_net_netmask(void);
|
||||||
u64 cleonos_sys_net_udp_send(const cleonos_net_udp_send_req *req);
|
u64 cleonos_sys_net_gateway(void);
|
||||||
u64 cleonos_sys_net_udp_recv(cleonos_net_udp_recv_req *req);
|
u64 cleonos_sys_net_dns_server(void);
|
||||||
|
u64 cleonos_sys_net_ping(u64 dst_ipv4_be, u64 poll_budget);
|
||||||
|
u64 cleonos_sys_net_udp_send(const cleonos_net_udp_send_req *req);
|
||||||
|
u64 cleonos_sys_net_udp_recv(cleonos_net_udp_recv_req *req);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -416,13 +416,25 @@ u64 cleonos_sys_net_available(void) {
|
|||||||
return cleonos_syscall(CLEONOS_SYSCALL_NET_AVAILABLE, 0ULL, 0ULL, 0ULL);
|
return cleonos_syscall(CLEONOS_SYSCALL_NET_AVAILABLE, 0ULL, 0ULL, 0ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 cleonos_sys_net_ipv4_addr(void) {
|
u64 cleonos_sys_net_ipv4_addr(void) {
|
||||||
return cleonos_syscall(CLEONOS_SYSCALL_NET_IPV4_ADDR, 0ULL, 0ULL, 0ULL);
|
return cleonos_syscall(CLEONOS_SYSCALL_NET_IPV4_ADDR, 0ULL, 0ULL, 0ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 cleonos_sys_net_ping(u64 dst_ipv4_be, u64 poll_budget) {
|
u64 cleonos_sys_net_netmask(void) {
|
||||||
return cleonos_syscall(CLEONOS_SYSCALL_NET_PING, dst_ipv4_be, poll_budget, 0ULL);
|
return cleonos_syscall(CLEONOS_SYSCALL_NET_NETMASK, 0ULL, 0ULL, 0ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 cleonos_sys_net_gateway(void) {
|
||||||
|
return cleonos_syscall(CLEONOS_SYSCALL_NET_GATEWAY, 0ULL, 0ULL, 0ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 cleonos_sys_net_dns_server(void) {
|
||||||
|
return cleonos_syscall(CLEONOS_SYSCALL_NET_DNS_SERVER, 0ULL, 0ULL, 0ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 cleonos_sys_net_ping(u64 dst_ipv4_be, u64 poll_budget) {
|
||||||
|
return cleonos_syscall(CLEONOS_SYSCALL_NET_PING, dst_ipv4_be, poll_budget, 0ULL);
|
||||||
|
}
|
||||||
|
|
||||||
u64 cleonos_sys_net_udp_send(const cleonos_net_udp_send_req *req) {
|
u64 cleonos_sys_net_udp_send(const cleonos_net_udp_send_req *req) {
|
||||||
return cleonos_syscall(CLEONOS_SYSCALL_NET_UDP_SEND, (u64)req, 0ULL, 0ULL);
|
return cleonos_syscall(CLEONOS_SYSCALL_NET_UDP_SEND, (u64)req, 0ULL, 0ULL);
|
||||||
|
|||||||
2
clks
2
clks
Submodule clks updated: f7c89a3420...9c23c272d0
@@ -83,7 +83,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
- `/proc/<pid>`:指定 PID 快照文本
|
- `/proc/<pid>`:指定 PID 快照文本
|
||||||
- `/proc` 为只读;写入类 syscall 不支持。
|
- `/proc` 为只读;写入类 syscall 不支持。
|
||||||
|
|
||||||
## 4. Syscall 列表(0~99)
|
## 4. Syscall 列表(0~102)
|
||||||
|
|
||||||
### 0 `CLEONOS_SYSCALL_LOG_WRITE`
|
### 0 `CLEONOS_SYSCALL_LOG_WRITE`
|
||||||
|
|
||||||
@@ -740,7 +740,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
|
|
||||||
- 参数:无
|
- 参数:无
|
||||||
- 返回:当前 IPv4 地址(`u32`,以网络字节序放在返回值低 32 位)。
|
- 返回:当前 IPv4 地址(`u32`,以网络字节序放在返回值低 32 位)。
|
||||||
- 说明:当前默认静态地址为 `10.0.2.15`(QEMU usernet 常见配置)。
|
- 说明:优先使用 DHCP 自动获取地址;若 DHCP 失败回退到 `10.0.2.15`(QEMU usernet 常见默认值)。
|
||||||
|
|
||||||
### 97 `CLEONOS_SYSCALL_NET_PING`
|
### 97 `CLEONOS_SYSCALL_NET_PING`
|
||||||
|
|
||||||
@@ -762,6 +762,24 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
- `arg0`: `struct { u64 out_payload_ptr; u64 payload_capacity; u64 out_src_ipv4_ptr; u64 out_src_port_ptr; u64 out_dst_port_ptr; } *req`
|
- `arg0`: `struct { u64 out_payload_ptr; u64 payload_capacity; u64 out_src_ipv4_ptr; u64 out_src_port_ptr; u64 out_dst_port_ptr; } *req`
|
||||||
- 返回:实际拷贝到 `out_payload_ptr` 的字节数;无数据/失败返回 `0`。
|
- 返回:实际拷贝到 `out_payload_ptr` 的字节数;无数据/失败返回 `0`。
|
||||||
- 说明:`out_src_*`/`out_dst_*` 指针可为 `0`(表示不关心该字段)。
|
- 说明:`out_src_*`/`out_dst_*` 指针可为 `0`(表示不关心该字段)。
|
||||||
|
|
||||||
|
### 100 `CLEONOS_SYSCALL_NET_NETMASK`
|
||||||
|
|
||||||
|
- 参数:无
|
||||||
|
- 返回:当前 IPv4 子网掩码(`u32`,网络字节序,位于返回值低 32 位)。
|
||||||
|
- 说明:优先使用 DHCP 下发值;若 DHCP 未提供则按回退策略填充。
|
||||||
|
|
||||||
|
### 101 `CLEONOS_SYSCALL_NET_GATEWAY`
|
||||||
|
|
||||||
|
- 参数:无
|
||||||
|
- 返回:当前 IPv4 默认网关(`u32`,网络字节序,位于返回值低 32 位)。
|
||||||
|
- 说明:优先使用 DHCP 下发值;若 DHCP 未提供则按回退策略填充。
|
||||||
|
|
||||||
|
### 102 `CLEONOS_SYSCALL_NET_DNS_SERVER`
|
||||||
|
|
||||||
|
- 参数:无
|
||||||
|
- 返回:当前 DNS 服务器 IPv4(`u32`,网络字节序,位于返回值低 32 位)。
|
||||||
|
- 说明:优先使用 DHCP 下发值;若 DHCP 未提供则按回退策略填充。
|
||||||
|
|
||||||
## 5. 用户态封装函数
|
## 5. 用户态封装函数
|
||||||
|
|
||||||
@@ -795,7 +813,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
- `cleonos_sys_disk_present()` / `cleonos_sys_disk_size_bytes()` / `cleonos_sys_disk_sector_count()`
|
- `cleonos_sys_disk_present()` / `cleonos_sys_disk_size_bytes()` / `cleonos_sys_disk_sector_count()`
|
||||||
- `cleonos_sys_disk_formatted()` / `cleonos_sys_disk_format_fat32()` / `cleonos_sys_disk_mount()` / `cleonos_sys_disk_mounted()` / `cleonos_sys_disk_mount_path()`
|
- `cleonos_sys_disk_formatted()` / `cleonos_sys_disk_format_fat32()` / `cleonos_sys_disk_mount()` / `cleonos_sys_disk_mounted()` / `cleonos_sys_disk_mount_path()`
|
||||||
- `cleonos_sys_disk_read_sector()` / `cleonos_sys_disk_write_sector()`
|
- `cleonos_sys_disk_read_sector()` / `cleonos_sys_disk_write_sector()`
|
||||||
- `cleonos_sys_net_available()` / `cleonos_sys_net_ipv4_addr()` / `cleonos_sys_net_ping()`
|
- `cleonos_sys_net_available()` / `cleonos_sys_net_ipv4_addr()` / `cleonos_sys_net_netmask()` / `cleonos_sys_net_gateway()` / `cleonos_sys_net_dns_server()` / `cleonos_sys_net_ping()`
|
||||||
- `cleonos_sys_net_udp_send()` / `cleonos_sys_net_udp_recv()`
|
- `cleonos_sys_net_udp_send()` / `cleonos_sys_net_udp_recv()`
|
||||||
|
|
||||||
## 6. 开发注意事项
|
## 6. 开发注意事项
|
||||||
@@ -807,7 +825,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
|
|
||||||
## 7. Wine 兼容说明
|
## 7. Wine 兼容说明
|
||||||
|
|
||||||
- `wine/cleonos_wine_lib/runner.py` 当前已覆盖到 `0..99`(含 `DL_*`、`FB_*`、`KERNEL_VERSION`、`DISK_*`、`NET_*`)。
|
- `wine/cleonos_wine_lib/runner.py` 当前已覆盖到 `0..102`(含 `DL_*`、`FB_*`、`KERNEL_VERSION`、`DISK_*`、`NET_*`)。
|
||||||
- `DL_*`(`77..79`)在 Wine 中为“可运行兼容”实现:
|
- `DL_*`(`77..79`)在 Wine 中为“可运行兼容”实现:
|
||||||
- `DL_OPEN`:加载 guest ELF 到当前 Unicorn 地址空间,返回稳定 `handle`,并做引用计数。
|
- `DL_OPEN`:加载 guest ELF 到当前 Unicorn 地址空间,返回稳定 `handle`,并做引用计数。
|
||||||
- `DL_SYM`:解析 ELF `SYMTAB/DYNSYM` 并返回 guest 可调用地址。
|
- `DL_SYM`:解析 ELF `SYMTAB/DYNSYM` 并返回 guest 可调用地址。
|
||||||
@@ -824,7 +842,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
|||||||
- `DISK_FORMAT_FAT32` 会初始化/重置 Wine rootfs 下的虚拟磁盘目录。
|
- `DISK_FORMAT_FAT32` 会初始化/重置 Wine rootfs 下的虚拟磁盘目录。
|
||||||
- `DISK_MOUNT`/`DISK_MOUNT_PATH` 支持挂载点管理,并与 `FS_MKDIR/WRITE/APPEND/REMOVE` 的路径规则联动。
|
- `DISK_MOUNT`/`DISK_MOUNT_PATH` 支持挂载点管理,并与 `FS_MKDIR/WRITE/APPEND/REMOVE` 的路径规则联动。
|
||||||
- `DISK_READ_SECTOR`/`DISK_WRITE_SECTOR`(`93..94`)在 Wine 中已实现为 512B 原始扇区读写(host 文件后端)。
|
- `DISK_READ_SECTOR`/`DISK_WRITE_SECTOR`(`93..94`)在 Wine 中已实现为 512B 原始扇区读写(host 文件后端)。
|
||||||
- 网络 syscall(`95..99`)在 Wine 当前为兼容占位实现(统一返回 `0`);即 Wine 运行模式下不会提供真实网络收发。
|
- 网络 syscall(`95..102`)在 Wine 当前为兼容占位实现(统一返回 `0`);即 Wine 运行模式下不会提供真实网络收发。
|
||||||
- Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。
|
- Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。
|
||||||
- Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0`,`AUDIO_PLAY_TONE=0`,`AUDIO_STOP=1`。
|
- Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0`,`AUDIO_PLAY_TONE=0`,`AUDIO_STOP=1`。
|
||||||
- Wine 版本号策略固定为 `85.0.0-wine`(历史兼容号;不会随 syscall 扩展继续增长)。
|
- Wine 版本号策略固定为 `85.0.0-wine`(历史兼容号;不会随 syscall 扩展继续增长)。
|
||||||
|
|||||||
Reference in New Issue
Block a user