diff --git a/repos/dde_linux/lib/mk/vfs_legacy_lxip.mk b/repos/dde_linux/lib/mk/vfs_legacy_lxip.mk
deleted file mode 100644
index 0ba8420262..0000000000
--- a/repos/dde_linux/lib/mk/vfs_legacy_lxip.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-SHARED_LIB = yes
-
-VFS_DIR = $(REP_DIR)/src/lib/vfs/legacy_lxip
-LXIP_DIR = $(REP_DIR)/src/lib/legacy_lxip
-
-LIBS += legacy_lxip lxip_include
-INC_DIR += $(VFS_DIR)
-LD_OPT += --version-script=$(VFS_DIR)/symbol.map
-SRC_CC = vfs.cc
-
-vpath %.cc $(REP_DIR)/src/lib/vfs/legacy_lxip
-
-SETUP_SUFFIX =
-CC_OPT += -DSETUP_SUFFIX=$(SETUP_SUFFIX)
-
-CC_OPT += -U__linux__ -D__KERNEL__
-CC_OPT += -DCONFIG_INET -DCONFIG_BASE_SMALL=0 -DCONFIG_DEBUG_LOCK_ALLOC \
- -DCONFIG_IP_PNP_DHCP
-
-CC_C_OPT += -include $(LXIP_DIR)/include/lx_emul.h
-CC_CXX_OPT += -fpermissive
-
-CC_CXX_WARN_STRICT =
diff --git a/repos/dde_linux/recipes/src/vfs_legacy_lxip/content.mk b/repos/dde_linux/recipes/src/vfs_legacy_lxip/content.mk
deleted file mode 100644
index dc8892d243..0000000000
--- a/repos/dde_linux/recipes/src/vfs_legacy_lxip/content.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-LIB_MK := $(addprefix lib/mk/,legacy_lxip.mk lxip_include.mk vfs_legacy_lxip.mk)
-
-PORT_DIR := $(call port_dir,$(REP_DIR)/ports/dde_linux)
-
-MIRROR_FROM_REP_DIR := $(LIB_MK) \
- lib/import/import-lxip_include.mk \
- include/lxip src/include/legacy src/lib/legacy/lx_kit \
- src/lib/lx_kit/spec \
- $(foreach SPEC, \
- arm_v6 arm_v7 arm_v8 x86 x86_32 x86_64, \
- src/include/spec/$(SPEC)) \
- $(shell cd $(REP_DIR); find src/lib/legacy_lxip -type f) \
- $(shell cd $(REP_DIR); find src/lib/vfs -type f)
-
-MIRROR_FROM_PORT_DIR := $(shell cd $(PORT_DIR); find src/lib/lxip -type f)
-
-content: $(MIRROR_FROM_REP_DIR) $(MIRROR_FROM_PORT_DIR)
-
-$(MIRROR_FROM_REP_DIR):
- $(mirror_from_rep_dir)
-
-$(MIRROR_FROM_PORT_DIR):
- mkdir -p $(dir $@)
- cp -r $(PORT_DIR)/$@ $@
-
-content: LICENSE
-LICENSE:
- ( echo "LxIP is based on Linux, which is licensed under the"; \
- echo "GNU General Public License version 2, see:"; \
- echo "https://www.kernel.org/pub/linux/kernel/COPYING" ) > $@
diff --git a/repos/dde_linux/recipes/src/vfs_legacy_lxip/hash b/repos/dde_linux/recipes/src/vfs_legacy_lxip/hash
deleted file mode 100644
index eef384c8f7..0000000000
--- a/repos/dde_linux/recipes/src/vfs_legacy_lxip/hash
+++ /dev/null
@@ -1 +0,0 @@
-2023-11-08 292058fabece5e1c6823163b0c61846d65313e5d
diff --git a/repos/dde_linux/recipes/src/vfs_legacy_lxip/used_apis b/repos/dde_linux/recipes/src/vfs_legacy_lxip/used_apis
deleted file mode 100644
index 1a6748cba0..0000000000
--- a/repos/dde_linux/recipes/src/vfs_legacy_lxip/used_apis
+++ /dev/null
@@ -1,7 +0,0 @@
-base
-nic_session
-os
-so
-timer_session
-vfs
-format
diff --git a/repos/dde_linux/src/lib/vfs/legacy_lxip/symbol.map b/repos/dde_linux/src/lib/vfs/legacy_lxip/symbol.map
deleted file mode 100644
index 58e4ff57a8..0000000000
--- a/repos/dde_linux/src/lib/vfs/legacy_lxip/symbol.map
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- global:
-
- vfs_file_system_factory;
-
- local:
-
- *;
-};
diff --git a/repos/dde_linux/src/lib/vfs/legacy_lxip/vfs.cc b/repos/dde_linux/src/lib/vfs/legacy_lxip/vfs.cc
deleted file mode 100644
index ce1775daa3..0000000000
--- a/repos/dde_linux/src/lib/vfs/legacy_lxip/vfs.cc
+++ /dev/null
@@ -1,2055 +0,0 @@
-/*
- * \brief lxip-based socket file system
- * \author Christian Helmuth
- * \author Josef Soentgen
- * \author Emery Hemingway
- * \date 2016-02-01
- */
-
-/*
- * Copyright (C) 2015-2018 Genode Labs GmbH
- *
- * This file is distributed under the terms of the GNU General Public License
- * version 2.
- */
-
-/* Genode includes */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* format-string includes */
-#include
-
-/* Lxip includes */
-#include
-#include
-
-/* Lx_kit */
-#include
-#include
-
-
-namespace Linux {
- #include
- #include
-
- #include
- #include
- #include
- #include
- extern int sock_setsockopt(socket *sock, int level,
- int op, char __user *optval,
- unsigned int optlen);
- extern int sock_getsockopt(socket *sock, int level,
- int op, char __user *optval,
- int __user *optlen);
- socket *sock_alloc(void);
- #include
-
- enum {
- POLLIN_SET = (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR),
- POLLOUT_SET = (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR),
- POLLEX_SET = (POLLPRI)
- };
-}
-
-
-namespace {
-
-long get_port(char const *p)
-{
- long tmp = -1;
-
- while (*++p) {
- if (*p == ':') {
- Genode::ascii_to_unsigned(++p, tmp, 10);
- break;
- }
- }
- return tmp;
-}
-
-
-unsigned get_addr(char const *p)
-{
- unsigned char to[4] = { 0, 0, 0, 0};
-
- for (unsigned char &c : to) {
-
- unsigned long result = 0;
- p += Genode::ascii_to_unsigned(p, result, 10);
-
- c = result;
-
- if (*p == '.') ++p;
- if (*p == 0) break;
- };
-
- return (to[0]<<0)|(to[1]<<8)|(to[2]<<16)|(to[3]<<24);
-}
-
-
-long get_family(char const *p)
-{
- long tmp = -1;
-
- while (*p) {
- if (*p == ';') {
- Genode::ascii_to_unsigned(++p, tmp, 1);
- break;
- }
- p++;
- }
- return tmp;
-}
-
-} /* unnamed namespace */
-
-namespace Lxip {
-
- using namespace Linux;
-
- struct Protocol_dir;
- struct Socket_dir;
-
- class Protocol_dir_impl;
-
- enum {
- MAX_SOCKETS = 128, /* 3 */
- MAX_SOCKET_NAME_LEN = 3 + 1, /* + \0 */
- MAX_DATA_LEN = 32, /* 255.255.255.255:65536 + something */
- };
-}
-
-
-namespace Vfs {
-
- using namespace Genode;
-
- struct Node;
- struct Directory;
- struct File;
-
- class Lxip_file;
- class Lxip_data_file;
- class Lxip_bind_file;
- class Lxip_accept_file;
- class Lxip_connect_file;
- class Lxip_listen_file;
- class Lxip_local_file;
- class Lxip_remote_file;
- class Lxip_peek_file;
-
- class Lxip_socket_dir;
- struct Lxip_socket_handle;
-
- class Lxip_link_state_file;
- class Lxip_address_file;
-
- struct Lxip_vfs_handle;
- class Lxip_vfs_file_handle;
- class Lxip_vfs_dir_handle;
- class Lxip_file_system;
-
- typedef Genode::List > Lxip_vfs_file_handles;
-}
-
-
-/***************
- ** Vfs nodes **
- ***************/
-
-struct Vfs::Node
-{
- char const *_name;
-
- Node(char const *name) : _name(name) { }
-
- virtual ~Node() { }
-
- char const *name() { return _name; }
-
- virtual void close() { }
-};
-
-
-struct Vfs::File : Vfs::Node
-{
- Lxip_vfs_file_handles handles;
-
- File(char const *name) : Node(name) { }
-
- virtual ~File() { }
-
- /**
- * Read or write operation would block exception
- */
- struct Would_block { };
-
- /**
- * Check for data to read or write
- */
- virtual bool poll() { return true; }
-
- virtual Lxip::ssize_t write(Lxip_vfs_file_handle &,
- Const_byte_range_ptr const &, file_size)
- {
- Genode::error(name(), " not writeable");
- return -1;
- }
-
- virtual Lxip::ssize_t read(Lxip_vfs_file_handle &,
- Byte_range_ptr const &, file_size)
- {
- Genode::error(name(), " not readable");
- return -1;
- }
-
- virtual File_io_service::Sync_result sync() {
- return File_io_service::Sync_result::SYNC_OK; }
-};
-
-
-struct Vfs::Directory : Vfs::Node
-{
- Directory(char const *name) : Node(name) { }
-
- virtual ~Directory() { };
-
- virtual Vfs::Node *child(char const *) = 0;
- virtual file_size num_dirent() = 0;
-
- typedef Vfs::Directory_service::Open_result Open_result;
- virtual Open_result open(Vfs::File_system &fs,
- Genode::Allocator &alloc,
- char const*, unsigned, Vfs::Vfs_handle**) = 0;
-
- virtual Lxip::ssize_t read(Byte_range_ptr const &, file_size seek_offset) = 0;
-};
-
-
-struct Lxip::Protocol_dir : Vfs::Directory
-{
- enum Type { TYPE_STREAM, TYPE_DGRAM };
-
- virtual char const *top_dir() = 0;
- virtual Type type() = 0;
- virtual unsigned adopt_socket(Lxip::Socket_dir &) = 0;
- virtual bool lookup_port(long) = 0;
- virtual void release(unsigned id) = 0;
-
- Protocol_dir(char const *name) : Vfs::Directory(name) { }
-};
-
-
-struct Lxip::Socket_dir : Vfs::Directory
-{
- typedef Vfs::Directory_service::Open_result Open_result;
-
- virtual Protocol_dir &parent() = 0;
- virtual char const *top_dir() = 0;
- virtual void bind(bool) = 0; /* bind to port */
- virtual long bind() = 0; /* return bound port */
- virtual bool lookup_port(long) = 0;
- virtual void connect(bool) = 0;
- virtual void listen(bool) = 0;
- virtual sockaddr_storage &remote_addr() = 0;
- virtual void close() = 0;
- virtual bool closed() const = 0;
-
- Socket_dir(char const *name) : Vfs::Directory(name) { }
-};
-
-
-struct Vfs::Lxip_vfs_handle : Vfs::Vfs_handle
-{
- typedef File_io_service:: Read_result Read_result;
- typedef File_io_service::Write_result Write_result;
- typedef File_io_service::Sync_result Sync_result;
-
- Lxip_vfs_handle(Vfs::File_system &fs, Allocator &alloc, int status_flags)
- : Vfs::Vfs_handle(fs, fs, alloc, status_flags) { }
-
- /**
- * Check if the file attached to this handle is ready to read
- */
- virtual bool read_ready() const = 0;
-
- virtual Read_result read(Byte_range_ptr const &dst, size_t &out_count) = 0;
- virtual Write_result write(Const_byte_range_ptr const &src, size_t &out_count) = 0;
-
- virtual Sync_result sync() {
- return Sync_result::SYNC_OK; }
-};
-
-
-struct Vfs::Lxip_vfs_file_handle final : Vfs::Lxip_vfs_handle
-{
- Lxip_vfs_file_handle(Lxip_vfs_file_handle const &);
- Lxip_vfs_file_handle &operator = (Lxip_vfs_file_handle const &);
-
- Vfs::File *file;
-
- /* file association element */
- List_element file_le { this };
-
- /* notification elements */
- typedef Genode::Fifo_element Fifo_element;
- typedef Genode::Fifo Fifo;
-
- Fifo_element read_ready_elem { *this };
-
- char content_buffer[Lxip::MAX_DATA_LEN];
-
- Lxip_vfs_file_handle(Vfs::File_system &fs, Allocator &alloc, int status_flags,
- Vfs::File *file)
- : Lxip_vfs_handle(fs, alloc, status_flags), file(file)
- {
- if (file)
- file->handles.insert(&file_le);
- }
-
- ~Lxip_vfs_file_handle()
- {
- if (file)
- file->handles.remove(&file_le);
- }
-
- bool read_ready() const override {
- return (file) ? file->poll() : false; }
-
- Read_result read(Byte_range_ptr const &dst, size_t &out_count) override
- {
- if (!file) return Read_result::READ_ERR_INVALID;
- Lxip::ssize_t res = file->read(*this, dst, seek());
- if (res < 0) return Read_result::READ_ERR_IO;
- out_count = res;
- return Read_result::READ_OK;
- }
-
- Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override
- {
- if (!file) return Write_result::WRITE_ERR_INVALID;
- Lxip::ssize_t res = file->write(*this, src, seek());
- if (res < 0) return Write_result::WRITE_ERR_IO;
- out_count = res;
- return Write_result::WRITE_OK;
- }
-
- bool write_content_line(Const_byte_range_ptr const &src)
- {
- if (src.num_bytes > sizeof(content_buffer) - 2)
- return false;
-
- Genode::memcpy(content_buffer, src.start, src.num_bytes);
- content_buffer[src.num_bytes + 0] = '\n';
- content_buffer[src.num_bytes + 1] = '\0';
- return true;
- }
-
- virtual Sync_result sync() override {
- return (file) ? file->sync() : Sync_result::SYNC_ERR_INVALID; }
-};
-
-
-struct Vfs::Lxip_vfs_dir_handle final : Vfs::Lxip_vfs_handle
-{
- Vfs::Directory &dir;
-
- Lxip_vfs_dir_handle(Vfs::File_system &fs, Allocator &alloc, int status_flags,
- Vfs::Directory &dir)
- : Vfs::Lxip_vfs_handle(fs, alloc, status_flags),
- dir(dir) { }
-
- bool read_ready() const override { return true; }
-
- Read_result read(Byte_range_ptr const &dst, size_t &out_count) override
- {
- Lxip::ssize_t res = dir.read(dst, seek());
- if (res < 0) return Read_result::READ_ERR_IO;
- out_count = res;
- return Read_result::READ_OK;
- }
-
- Write_result write(Const_byte_range_ptr const &, size_t &) override {
- return Write_result::WRITE_ERR_INVALID; }
-};
-
-
-static Vfs::Env::User *_vfs_user_ptr;
-static Vfs::Lxip_vfs_file_handle::Fifo *_read_ready_waiters_ptr;
-
-
-static void poll_all()
-{
- if (_vfs_user_ptr)
- _vfs_user_ptr->wakeup_vfs_user();
-
- _read_ready_waiters_ptr->for_each(
- [&] (Vfs::Lxip_vfs_file_handle::Fifo_element &elem) {
- Vfs::Lxip_vfs_file_handle &handle = elem.object();
- if (handle.file) {
- if (handle.file->poll()) {
- /* do not notify again until notify_read_ready */
- _read_ready_waiters_ptr->remove(elem);
-
- handle.read_ready_response();
- }
- }
- });
-}
-
-
-/*****************************
- ** Lxip vfs specific nodes **
- *****************************/
-
-class Vfs::Lxip_file : public Vfs::File
-{
- protected:
-
- Lxip::Socket_dir &_parent;
- Linux::socket &_sock;
-
- int _write_err = 0;
-
- bool _sock_valid() { return _sock.sk != nullptr; }
-
- public:
-
- Lxip_file(Lxip::Socket_dir &p, Linux::socket &s, char const *name)
- : Vfs::File(name), _parent(p), _sock(s) { }
-
- virtual ~Lxip_file() { }
-
- /**
- * Dissolve relationship between handle and file, file and polling list.
- */
- void dissolve_handles()
- {
- Genode::List_element *le = handles.first();
- while (le) {
- Vfs::Lxip_vfs_file_handle *h = le->object();
- handles.remove(&h->file_le);
- h->file = nullptr;
- le = handles.first();
- }
- }
-
- File_io_service::Sync_result sync() override
- {
- return (_write_err)
- ? File_io_service::Sync_result::SYNC_ERR_INVALID
- : File_io_service::Sync_result::SYNC_OK;
- }
-};
-
-
-class Vfs::Lxip_data_file final : public Vfs::Lxip_file
-{
- public:
-
- Lxip_data_file(Lxip::Socket_dir &p, Linux::socket &s)
- : Lxip_file(p, s, "data") { }
-
- /********************
- ** File interface **
- ********************/
-
- bool poll() override
- {
- using namespace Linux;
-
- file f;
- f.f_flags = 0;
- return (_sock.ops->poll(&f, &_sock, nullptr) & (POLLIN_SET));
- }
-
- Lxip::ssize_t write(Lxip_vfs_file_handle &,
- Const_byte_range_ptr const &src,
- file_size /* ignored */) override
- {
- using namespace Linux;
-
- if (!_sock_valid()) return -1;
-
- iovec iov { (void *)src.start, src.num_bytes };
-
- msghdr msg = create_msghdr(&_parent.remote_addr(),
- sizeof(sockaddr_in), src.num_bytes, &iov);
-
- Lxip::ssize_t res = _sock.ops->sendmsg(&_sock, &msg, src.num_bytes);
-
- if (res < 0) _write_err = res;
-
- return res;
- }
-
- Lxip::ssize_t read(Lxip_vfs_file_handle &handle,
- Byte_range_ptr const &dst,
- file_size /* ignored */) override
- {
- using namespace Linux;
-
- if (!_sock_valid()) return -1;
-
- iovec iov { dst.start, dst.num_bytes };
-
- msghdr msg = create_msghdr(nullptr, 0, dst.num_bytes, &iov);
-
- Lxip::ssize_t ret = _sock.ops->recvmsg(&_sock, &msg, dst.num_bytes, MSG_DONTWAIT);
- if (ret == -EAGAIN)
- throw Would_block();
-
- return ret;
- }
-};
-
-
-class Vfs::Lxip_peek_file final : public Vfs::Lxip_file
-{
- public:
-
- Lxip_peek_file(Lxip::Socket_dir &p, Linux::socket &s)
- : Lxip_file(p, s, "peek") { }
-
- /********************
- ** File interface **
- ********************/
-
- bool poll() override
- {
- /* can always peek */
- return true;
- }
-
- Lxip::ssize_t write(Lxip_vfs_file_handle &,
- Const_byte_range_ptr const &, file_size) override
- {
- return -1;
- }
-
- Lxip::ssize_t read(Lxip_vfs_file_handle &handle,
- Byte_range_ptr const &dst,
- file_size /* ignored */) override
- {
- using namespace Linux;
-
- if (!_sock_valid()) return -1;
-
- iovec iov { dst.start, dst.num_bytes };
-
- msghdr msg = create_msghdr(nullptr, 0, dst.num_bytes, &iov);
-
- Lxip::ssize_t ret = _sock.ops->recvmsg(&_sock, &msg, dst.num_bytes,
- MSG_DONTWAIT|MSG_PEEK);
- if (ret == -EAGAIN)
- return 0;
-
- return ret;
- }
-};
-
-
-class Vfs::Lxip_bind_file final : public Vfs::Lxip_file
-{
- private:
-
- long _port = -1;
-
- public:
-
- Lxip_bind_file(Lxip::Socket_dir &p, Linux::socket &s)
- : Lxip_file(p, s, "bind") { }
-
- long port() { return _port; }
-
- /********************
- ** File interface **
- ********************/
-
- Lxip::ssize_t write(Lxip_vfs_file_handle &handle,
- Const_byte_range_ptr const &src,
- file_size /* ignored */) override
- {
- using namespace Linux;
-
- if (!_sock_valid()) return -1;
-
- /* already bound to port */
- if (_port >= 0) return -1;
-
- if (!handle.write_content_line(src)) return -1;
-
- /* check if port is already used by other socket */
- long port = get_port(handle.content_buffer);
- if (port == -1) return -1;
- if (_parent.lookup_port(port)) return -1;
-
- /* port is free, try to bind it */
- sockaddr_storage addr_storage;
-
- sockaddr_in *addr = (sockaddr_in *)&addr_storage;
- addr->sin_port = htons(port);
- addr->sin_addr.s_addr = get_addr(handle.content_buffer);
- addr->sin_family = AF_INET;
-
- _write_err = _sock.ops->bind(&_sock, (sockaddr*)addr, sizeof(addr_storage));
- if (_write_err != 0) return -1;
-
- _port = port;
-
- _parent.bind(true);
-
- return src.num_bytes;
- }
-
- Lxip::ssize_t read(Lxip_vfs_file_handle &handle,
- Byte_range_ptr const &dst,
- file_size /* ignored */) override
- {
- if (dst.num_bytes < sizeof(handle.content_buffer))
- return -1;
-
- Genode::size_t const n = Genode::strlen(handle.content_buffer);
- Genode::memcpy(dst.start, handle.content_buffer, n);
-
- return n;
- }
-};
-
-
-class Vfs::Lxip_listen_file final : public Vfs::Lxip_file
-{
- private:
-
- unsigned long _backlog = ~0UL;
-
- public:
-
- Lxip_listen_file(Lxip::Socket_dir &p, Linux::socket &s)
- : Lxip_file(p, s, "listen") { }
-
- /********************
- ** File interface **
- ********************/
-
- Lxip::ssize_t write(Lxip_vfs_file_handle &handle,
- Const_byte_range_ptr const &src,
- file_size /* ignored */) override
- {
- if (!_sock_valid()) return -1;
-
- /* write-once */
- if (_backlog != ~0UL) return -1;
-
- if (!handle.write_content_line(src)) return -1;
-
- Genode::ascii_to_unsigned(
- handle.content_buffer, _backlog, sizeof(handle.content_buffer));
-
- if (_backlog == ~0UL) return -1;
-
- _write_err = _sock.ops->listen(&_sock, _backlog);
- if (_write_err != 0) {
- handle.write_content_line(Const_byte_range_ptr("", 0));
- return -1;
- }
-
- _parent.listen(true);
-
- return src.num_bytes;
- }
-
- Lxip::ssize_t read(Lxip_vfs_file_handle &handle,
- Byte_range_ptr const &dst,
- file_size /* ignored */) override
- {
- return Format::snprintf(dst.start, dst.num_bytes, "%lu\n", _backlog);
- }
-};
-
-
-class Vfs::Lxip_connect_file final : public Vfs::Lxip_file
-{
- private:
-
- bool _connecting = false;
- bool _is_connected = false;
-
- public:
-
- Lxip_connect_file(Lxip::Socket_dir &p, Linux::socket &s)
- : Lxip_file(p, s, "connect") { }
-
- /********************
- ** File interface **
- ********************/
-
- bool poll() override
- {
- /*
- * The connect file is considered readable when the socket is
- * writeable (connected or error).
- */
-
- using namespace Linux;
-
- file f;
- f.f_flags = 0;
- return (_sock.ops->poll(&f, &_sock, nullptr) & (POLLOUT_SET));
- }
-
- Lxip::ssize_t write(Lxip_vfs_file_handle &handle,
- Const_byte_range_ptr const &src,
- file_size /* ignored */) override
- {
- using namespace Linux;
-
- if (!_sock_valid()) return -1;
-
- if (!handle.write_content_line(src)) return -1;
-
- long const port = get_port(handle.content_buffer);
- long const family = get_family(handle.content_buffer);
- if (port == -1 && family) return -1;
-
- sockaddr_storage addr_storage;
-
- sockaddr_in *addr = (sockaddr_in *)&addr_storage;
- addr->sin_port = htons(port);
- addr->sin_addr.s_addr = get_addr(handle.content_buffer);
- addr->sin_family = family == 0 ? AF_UNSPEC : AF_INET;
-
- _write_err = _sock.ops->connect(&_sock, (sockaddr *)addr, sizeof(addr_storage), O_NONBLOCK);
-
- if (family == AF_UNSPEC) {
- _is_connected = false;
- _connecting = false;
- _parent.connect(false);
- return src.num_bytes;
- }
-
- switch (_write_err) {
- case Lxip::Io_result::LINUX_EINPROGRESS:
- _connecting = true;
- _write_err = 0;
- return src.num_bytes;
-
- case Lxip::Io_result::LINUX_EALREADY:
- return -1;
-
- case Lxip::Io_result::LINUX_EISCONN:
- /*
- * Connecting on an already connected socket is an error.
- * If we get this error after we got EINPROGRESS it is
- * fine.
- */
- if (_is_connected || !_connecting) return -1;
- _is_connected = true;
- _write_err = 0;
- break;
-
- default:
- if (_write_err != 0) return -1;
- _is_connected = true;
- break;
- }
-
- sockaddr_in *remote_addr = (sockaddr_in *)&_parent.remote_addr();
- remote_addr->sin_port = htons(port);
- remote_addr->sin_addr.s_addr = get_addr(handle.content_buffer);
- remote_addr->sin_family = AF_INET;
-
- _parent.connect(true);
-
- return src.num_bytes;
- }
-
- Lxip::ssize_t read(Lxip_vfs_file_handle &handle,
- Byte_range_ptr const &dst,
- file_size /* ignored */) override
- {
- int so_error = 0;
- int opt_len = sizeof(so_error);
- int res = sock_getsockopt(&_sock, SOL_SOCKET, SO_ERROR, (char*)&so_error, &opt_len);
-
- if (res != 0) {
- Genode::error("Vfs::Lxip_connect_file::read(): getsockopt() failed");
- return -1;
- }
-
- switch (so_error) {
- case 0:
- return Format::snprintf(dst.start, dst.num_bytes, "connected");
- case Linux::ECONNREFUSED:
- return Format::snprintf(dst.start, dst.num_bytes, "connection refused");
- case Linux::EHOSTUNREACH:
- return Format::snprintf(dst.start, dst.num_bytes, "no route to host");
- default:
- return Format::snprintf(dst.start, dst.num_bytes, "unknown error");
- }
- }
-};
-
-
-class Vfs::Lxip_local_file final : public Vfs::Lxip_file
-{
- public:
-
- Lxip_local_file(Lxip::Socket_dir &p, Linux::socket &s)
- : Lxip_file(p, s, "local") { }
-
- /********************
- ** File interface **
- ********************/
-
- Lxip::ssize_t read(Lxip_vfs_file_handle &handle,
- Byte_range_ptr const &dst,
- file_size /* ignored */) override
- {
- using namespace Linux;
-
- if (!_sock_valid()) return -1;
-
- if (dst.num_bytes < sizeof(handle.content_buffer))
- return -1;
-
- sockaddr_storage addr_storage;
- sockaddr_in *addr = (sockaddr_in *)&addr_storage;
-
- int out_len = sizeof(addr_storage);
- int const res = _sock.ops->getname(&_sock, (sockaddr *)addr, &out_len, 0);
- if (res < 0) return -1;
-
- in_addr const i_addr = addr->sin_addr;
- unsigned char const *a = (unsigned char *)&i_addr.s_addr;
- unsigned char const *p = (unsigned char *)&addr->sin_port;
- return Format::snprintf(dst.start, dst.num_bytes,
- "%d.%d.%d.%d:%u\n",
- a[0], a[1], a[2], a[3], (p[0]<<8)|(p[1]<<0));
- }
-};
-
-
-class Vfs::Lxip_remote_file final : public Vfs::Lxip_file
-{
- public:
-
- Lxip_remote_file(Lxip::Socket_dir &p, Linux::socket &s)
- : Lxip_file(p, s, "remote") { }
-
- /********************
- ** File interface **
- ********************/
-
- bool poll() override
- {
- using namespace Linux;
-
- file f;
- f.f_flags = 0;
-
- switch (_parent.parent().type()) {
- case Lxip::Protocol_dir::TYPE_DGRAM:
- return (_sock.ops->poll(&f, &_sock, nullptr) & (POLLIN_SET));
-
- case Lxip::Protocol_dir::TYPE_STREAM:
- return true;
- }
-
- return false;
- }
-
- Lxip::ssize_t read(Lxip_vfs_file_handle &handle,
- Byte_range_ptr const &dst,
- file_size /* ignored */) override
- {
- using namespace Linux;
-
- if (!_sock_valid()) return -1;
-
- sockaddr_storage addr_storage;
- sockaddr_in *addr = (sockaddr_in *)&addr_storage;
-
- switch (_parent.parent().type()) {
- case Lxip::Protocol_dir::TYPE_DGRAM:
- {
- /* peek the sender address of the next packet */
-
- /* buffer not used */
- iovec iov { handle.content_buffer, sizeof(handle.content_buffer) };
-
- msghdr msg = create_msghdr(addr, sizeof(addr_storage),
- sizeof(handle.content_buffer), &iov);
-
- int const res = _sock.ops->recvmsg(&_sock, &msg, 0, MSG_DONTWAIT|MSG_PEEK);
- if (res == -EAGAIN)
- throw Would_block();
-
- if (res < 0) return -1;
- }
- break;
- case Lxip::Protocol_dir::TYPE_STREAM:
- {
- int out_len = sizeof(addr_storage);
- int const res = _sock.ops->getname(&_sock, (sockaddr *)addr, &out_len, 1);
- if (res < 0) return -1;
- }
- break;
- }
-
- in_addr const i_addr = addr->sin_addr;
- unsigned char const *a = (unsigned char *)&i_addr.s_addr;
- unsigned char const *p = (unsigned char *)&addr->sin_port;
- return Format::snprintf(dst.start, dst.num_bytes,
- "%d.%d.%d.%d:%u\n",
- a[0], a[1], a[2], a[3], (p[0]<<8)|(p[1]<<0));
- }
-
- Lxip::ssize_t write(Lxip_vfs_file_handle &handle,
- Const_byte_range_ptr const &src,
- file_size /* ignored */) override
- {
- using namespace Linux;
-
- if (!handle.write_content_line(src)) return -1;
-
- long const port = get_port(handle.content_buffer);
- if (port == -1) return -1;
-
- sockaddr_in *remote_addr = (sockaddr_in *)&_parent.remote_addr();
- remote_addr->sin_port = htons(port);
- remote_addr->sin_addr.s_addr = get_addr(handle.content_buffer);
- remote_addr->sin_family = AF_INET;
-
- return src.num_bytes;
- }
-};
-
-
-class Vfs::Lxip_accept_file final : public Vfs::Lxip_file
-{
- public:
-
- Lxip_accept_file(Lxip::Socket_dir &p, Linux::socket &s)
- : Lxip_file(p, s, "accept") { }
-
- /********************
- ** File interface **
- ********************/
-
- bool poll() override
- {
- using namespace Linux;
-
- file f;
- f.f_flags = 0;
-
- return (_sock.ops->poll(&f, &_sock, nullptr) & (POLLIN));
- }
-
- Lxip::ssize_t read(Lxip_vfs_file_handle &handle,
- Byte_range_ptr const &dst,
- file_size /* ignored */) override
- {
- using namespace Linux;
-
- if (!_sock_valid()) return -1;
-
- file f;
- f.f_flags = 0;
-
- if (_sock.ops->poll(&f, &_sock, nullptr) & (POLLIN)) {
- copy_cstring(dst.start, "1\n", dst.num_bytes);
- return Genode::strlen(dst.start);
- }
-
- throw Would_block();
- }
-};
-
-
-class Vfs::Lxip_socket_dir final : public Lxip::Socket_dir
-{
- public:
-
- enum {
- ACCEPT_NODE, BIND_NODE, CONNECT_NODE,
- DATA_NODE, PEEK_NODE,
- LOCAL_NODE, LISTEN_NODE, REMOTE_NODE,
- ACCEPT_SOCKET_NODE,
- MAX_FILES
- };
-
- private:
-
- Genode::Allocator &_alloc;
- Lxip::Protocol_dir &_parent;
- Linux::socket &_sock;
-
- Vfs::File *_files[MAX_FILES];
-
- Linux::sockaddr_storage _remote_addr;
-
- unsigned _num_nodes()
- {
- unsigned num = 0;
- for (Vfs::File *n : _files) num += (n != nullptr);
- return num;
- }
-
- Lxip_accept_file _accept_file { *this, _sock };
- Lxip_bind_file _bind_file { *this, _sock };
- Lxip_connect_file _connect_file { *this, _sock };
- Lxip_data_file _data_file { *this, _sock };
- Lxip_peek_file _peek_file { *this, _sock };
- Lxip_listen_file _listen_file { *this, _sock };
- Lxip_local_file _local_file { *this, _sock };
- Lxip_remote_file _remote_file { *this, _sock };
-
- struct Accept_socket_file : Vfs::File
- {
- Accept_socket_file() : Vfs::File("accept_socket") { }
-
- } _accept_socket_file { };
-
- char _name[Lxip::MAX_SOCKET_NAME_LEN];
-
- Vfs::Directory_service::Open_result
- _accept_new_socket(Vfs::File_system &fs,
- Genode::Allocator &alloc,
- Vfs::Vfs_handle **out_handle);
-
- public:
-
- unsigned const id;
-
- Lxip_socket_dir(Genode::Allocator &alloc,
- Lxip::Protocol_dir &parent,
- Linux::socket &sock)
- :
- Lxip::Socket_dir(_name),
- _alloc(alloc), _parent(parent),
- _sock(sock), id(parent.adopt_socket(*this))
- {
- Format::snprintf(_name, sizeof(_name), "%u", id);
-
- for (Vfs::File * &file : _files) file = nullptr;
-
- _files[ACCEPT_NODE] = &_accept_file;
- _files[BIND_NODE] = &_bind_file;
- _files[CONNECT_NODE] = &_connect_file;
- _files[DATA_NODE] = &_data_file;
- _files[PEEK_NODE] = &_peek_file;
- _files[LISTEN_NODE] = &_listen_file;
- _files[LOCAL_NODE] = &_local_file;
- _files[REMOTE_NODE] = &_remote_file;
- }
-
- ~Lxip_socket_dir()
- {
- _accept_file.dissolve_handles();
- _bind_file.dissolve_handles();
- _connect_file.dissolve_handles();
- _data_file.dissolve_handles();
- _peek_file.dissolve_handles();
- _listen_file.dissolve_handles();
- _local_file.dissolve_handles();
- _remote_file.dissolve_handles();
-
- Linux::socket *sock = &_sock;
-
- if (sock->ops)
- sock->ops->release(sock);
-
- kfree(sock->wq);
- kfree(sock);
-
- _parent.release(id);
- }
-
- /**************************
- ** Socket_dir interface **
- **************************/
-
- Lxip::Protocol_dir &parent() override { return _parent; }
-
- Linux::sockaddr_storage &remote_addr() override { return _remote_addr; }
-
- char const *top_dir() override { return _parent.top_dir(); }
-
- Open_result
- open(Vfs::File_system &fs,
- Genode::Allocator &alloc,
- char const *path, unsigned mode, Vfs::Vfs_handle**out_handle) override
- {
- ++path;
-
- if (strcmp(path, "accept_socket") == 0)
- return _accept_new_socket(fs, alloc, out_handle);
-
- for (Vfs::File *f : _files) {
- if (f && Genode::strcmp(f->name(), path) == 0) {
- Vfs::Lxip_vfs_file_handle *handle = new (alloc)
- Vfs::Lxip_vfs_file_handle(fs, alloc, mode, f);
- *out_handle = handle;
- return Open_result::OPEN_OK;
- }
- }
-
- Genode::error(path, " is UNACCESSIBLE");
- return Vfs::Directory_service::OPEN_ERR_UNACCESSIBLE;
- }
-
- void bind(bool v) override { }
-
- long bind() override { return _bind_file.port(); }
-
- bool lookup_port(long port) override { return _parent.lookup_port(port); }
-
- void connect(bool v) override { }
-
- void listen(bool v) override
- {
- _files[ACCEPT_SOCKET_NODE] = v ? &_accept_socket_file : nullptr;
- }
-
- bool _closed = false;
-
- void close() override { _closed = true; }
- bool closed() const override { return _closed; }
-
-
- /*************************
- ** Directory interface **
- *************************/
-
- Vfs::Node *child(char const *name) override
- {
- for (Vfs::File *n : _files)
- if (n && Genode::strcmp(n->name(), name) == 0)
- return n;
-
- return nullptr;
- }
-
- file_size num_dirent() override { return _num_nodes(); }
-
- Lxip::ssize_t read(Byte_range_ptr const &dst,
- file_size seek_offset) override
- {
- typedef Vfs::Directory_service::Dirent Dirent;
-
- if (dst.num_bytes < sizeof(Dirent))
- return -1;
-
- size_t index = size_t(seek_offset / sizeof(Dirent));
-
- Dirent &out = *(Dirent*)dst.start;
-
- Vfs::Node *node = nullptr;
- for (Vfs::File *n : _files) {
- if (n) {
- if (index == 0) {
- node = n;
- break;
- }
- --index;
- }
- }
- if (!node) {
- out = {
- .fileno = index + 1,
- .type = Directory_service::Dirent_type::END,
- .rwx = { },
- .name = { } };
-
- return -1;
- }
-
- out = {
- .fileno = index + 1,
- .type = Directory_service::Dirent_type::TRANSACTIONAL_FILE,
- .rwx = Node_rwx::rw(),
- .name = { node->name() } };
-
- return sizeof(Dirent);
- }
-};
-
-
-struct Vfs::Lxip_socket_handle final : Vfs::Lxip_vfs_handle
-{
- Lxip_socket_dir socket_dir;
-
- Lxip_socket_handle(Vfs::File_system &fs,
- Genode::Allocator &alloc,
- Lxip::Protocol_dir &parent,
- Linux::socket &sock)
- :
- Lxip_vfs_handle(fs, alloc, 0),
- socket_dir(alloc, parent, sock)
- { }
-
- bool read_ready() const override { return true; }
-
- Read_result read(Byte_range_ptr const &dst, size_t &out_count) override
- {
- out_count = Format::snprintf(
- dst.start, dst.num_bytes, "%s/%s\n", socket_dir.parent().name(), socket_dir.name());
- return Read_result::READ_OK;
- }
-
- Write_result write(Const_byte_range_ptr const &, size_t &) override {
- return Write_result::WRITE_ERR_INVALID; }
-};
-
-
-Vfs::Directory_service::Open_result
-Vfs::Lxip_socket_dir::_accept_new_socket(Vfs::File_system &fs,
- Genode::Allocator &alloc,
- Vfs::Vfs_handle **out_handle)
-{
- using namespace Linux;
-
- Open_result res = Open_result::OPEN_ERR_UNACCESSIBLE;
- if (!_files[ACCEPT_SOCKET_NODE]) return res;
-
- socket *new_sock = sock_alloc();
-
- if (_sock.ops->accept(&_sock, new_sock, O_NONBLOCK)) {
- error("accept socket failed");
- kfree(new_sock);
- return res;
- }
-
- set_sock_wait(new_sock, 0);
- new_sock->type = _sock.type;
- new_sock->ops = _sock.ops;
-
- try {
- Vfs::Lxip_socket_handle *handle = new (alloc)
- Vfs::Lxip_socket_handle(fs, alloc, _parent, *new_sock);
- *out_handle = handle;
- return Vfs::Directory_service::Open_result::OPEN_OK;
- }
-
- catch (Genode::Out_of_ram) { res = Open_result::OPEN_ERR_OUT_OF_RAM; }
- catch (Genode::Out_of_caps) { res = Open_result::OPEN_ERR_OUT_OF_CAPS; }
- catch (...) { Genode::error("unhandle error during accept"); }
-
- kfree(new_sock);
- return res;
-};
-
-
-class Lxip::Protocol_dir_impl : public Protocol_dir
-{
- private:
-
- Genode::Allocator &_alloc;
- Vfs::File_system &_parent;
-
- struct New_socket_file : Vfs::File
- {
- New_socket_file() : Vfs::File("new_socket") { }
- } _new_socket_file { };
-
- Type const _type;
-
- /**************************
- ** Simple node registry **
- **************************/
-
- enum { MAX_NODES = Lxip::MAX_SOCKETS + 1 };
- Vfs::Node *_nodes[MAX_NODES];
-
- unsigned _num_nodes()
- {
- unsigned n = 0;
- for (Genode::size_t i = 0; i < MAX_NODES; i++)
- n += (_nodes[i] != nullptr);
- return n;
- }
-
- Vfs::Node **_unused_node()
- {
- for (Genode::size_t i = 0; i < MAX_NODES; i++)
- if (_nodes[i] == nullptr) return &_nodes[i];
- throw -1;
- }
-
- void _free_node(Vfs::Node *node)
- {
- for (Genode::size_t i = 0; i < MAX_NODES; i++)
- if (_nodes[i] == node) {
- _nodes[i] = nullptr;
- break;
- }
- }
-
- bool _is_root(const char *path)
- {
- return (Genode::strcmp(path, "") == 0) || (Genode::strcmp(path, "/") == 0);
- }
-
- Vfs::Directory_service::Open_result
- _open_new_socket(Vfs::File_system &fs,
- Genode::Allocator &alloc,
- Vfs::Vfs_handle **out_handle)
- {
- using namespace Linux;
-
- Vfs::Directory_service::Open_result res =
- Vfs::Directory_service::Open_result::OPEN_ERR_UNACCESSIBLE;
-
- socket *sock = nullptr;
-
- int type = (_type == Lxip::Protocol_dir::TYPE_STREAM)
- ? SOCK_STREAM : SOCK_DGRAM;
-
- if (sock_create_kern(nullptr, AF_INET, type, 0, &sock)) {
- kfree(sock);
- return res;
- }
-
- set_sock_wait(sock, 0);
-
- /* XXX always allow UDP broadcast */
- if (type == SOCK_DGRAM) {
- int enable = 1;
- sock_setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&enable, sizeof(enable));
- }
-
- try {
- Vfs::Lxip_socket_handle *handle = new (alloc)
- Vfs::Lxip_socket_handle(fs, alloc, *this, *sock);
- *out_handle = handle;
- return Vfs::Directory_service::Open_result::OPEN_OK;
- }
-
- catch (Genode::Out_of_ram) {
- res = Open_result::OPEN_ERR_OUT_OF_RAM; }
- catch (Genode::Out_of_caps) {
- res = Open_result::OPEN_ERR_OUT_OF_CAPS; }
- catch (...) { Genode::error("unhandle error during accept"); }
-
- kfree(sock);
- return res;
- }
-
- public:
-
- Protocol_dir_impl(Genode::Allocator &alloc,
- Vfs::File_system &parent,
- char const *name,
- Lxip::Protocol_dir::Type type)
- :
- Protocol_dir(name),
- _alloc(alloc), _parent(parent), _type(type)
- {
- for (Genode::size_t i = 0; i < MAX_NODES; i++) {
- _nodes[i] = nullptr;
- }
-
- _nodes[0] = &_new_socket_file;
- }
-
- ~Protocol_dir_impl() { }
-
- Vfs::Node *lookup(char const *path)
- {
- if (*path == '/') path++;
- if (*path == '\0') return this;
-
- char const *p = path;
- while (*++p && *p != '/');
-
- for (Genode::size_t i = 0; i < MAX_NODES; i++) {
- if (!_nodes[i]) continue;
-
- if (Genode::strcmp(_nodes[i]->name(), path, (p - path)) == 0) {
- Vfs::Directory *dir = dynamic_cast(_nodes[i]);
- if (!dir) return _nodes[i];
-
- Socket_dir *socket = dynamic_cast(_nodes[i]);
- if (socket && socket->closed())
- return nullptr;
-
- if (*p == '/') return dir->child(p+1);
- else return dir;
- }
- }
-
- return nullptr;
- }
-
- Vfs::Directory_service::Unlink_result unlink(char const *path)
- {
- Vfs::Node *node = lookup(path);
- if (!node) return Vfs::Directory_service::UNLINK_ERR_NO_ENTRY;
-
- Vfs::Directory *dir = dynamic_cast(node);
- if (!dir) return Vfs::Directory_service::UNLINK_ERR_NO_ENTRY;
-
- _free_node(node);
-
- Genode::destroy(&_alloc, dir);
-
- return Vfs::Directory_service::UNLINK_OK;
- }
-
- /****************************
- ** Protocol_dir interface **
- ****************************/
-
- char const *top_dir() override { return name(); }
-
- Type type() { return _type; }
-
- Open_result open(Vfs::File_system &fs,
- Genode::Allocator &alloc,
- char const *path, unsigned mode,
- Vfs::Vfs_handle **out_handle) override
- {
- if (strcmp(path, "/new_socket") == 0) {
- if (mode != 0) return Open_result::OPEN_ERR_NO_PERM;
- return _open_new_socket(fs, alloc, out_handle);
- }
-
- path++;
- char const *p = path;
- while (*++p && *p != '/');
-
- for (Genode::size_t i = 1; i < MAX_NODES; i++) {
- if (!_nodes[i]) continue;
- if (Genode::strcmp(_nodes[i]->name(), path, (p - path)) == 0) {
- Vfs::Directory *dir = dynamic_cast(_nodes[i]);
- if (dir) {
- path += (p - path);
- return dir->open(fs, alloc, path, mode, out_handle);
- }
- }
- }
-
- return Open_result::OPEN_ERR_UNACCESSIBLE;
- }
-
- unsigned adopt_socket(Lxip::Socket_dir &dir)
- {
- Vfs::Node **node = _unused_node();
- if (!node) throw -1;
-
- unsigned const id = ((unsigned char*)node - (unsigned char*)_nodes)/sizeof(*_nodes);
-
- *node = &dir;
- return id;
- }
-
- void release(unsigned id)
- {
- if (id < MAX_NODES)
- _nodes[id] = nullptr;
- }
-
- bool lookup_port(long port)
- {
- for (Genode::size_t i = 0; i < MAX_NODES; i++) {
- if (_nodes[i] == nullptr) continue;
-
- Lxip::Socket_dir *dir = dynamic_cast(_nodes[i]);
- if (dir && dir->bind() == port) return true;
- }
- return false;
- }
-
- /*************************
- ** Directory interface **
- *************************/
-
- Vfs::file_size num_dirent() override { return _num_nodes(); }
-
- Lxip::ssize_t read(Vfs::Byte_range_ptr const &dst,
- Vfs::file_size seek_offset) override
- {
- typedef Vfs::Directory_service::Dirent Dirent;
-
- if (dst.num_bytes < sizeof(Dirent))
- return -1;
-
- size_t index = size_t(seek_offset / sizeof(Dirent));
-
- Dirent &out = *(Dirent*)dst.start;
-
- Vfs::Node *node = nullptr;
- for (Vfs::Node *n : _nodes) {
- if (n) {
- if (index == 0) {
- node = n;
- break;
- }
- --index;
- }
- }
- if (!node) {
- out = {
- .fileno = index + 1,
- .type = Vfs::Directory_service::Dirent_type::END,
- .rwx = { },
- .name = { } };
-
- return -1;
- }
-
- typedef Vfs::Directory_service::Dirent_type Dirent_type;
-
- Dirent_type const type =
- dynamic_cast(node) ? Dirent_type::DIRECTORY :
- dynamic_cast(node) ? Dirent_type::TRANSACTIONAL_FILE
- : Dirent_type::END;
-
- Vfs::Node_rwx const rwx = (type == Dirent_type::DIRECTORY)
- ? Vfs::Node_rwx::rwx()
- : Vfs::Node_rwx::rw();
-
- out = {
- .fileno = index + 1,
- .type = type,
- .rwx = rwx,
- .name = { node->name() } };
-
- return sizeof(Dirent);
- }
-
- Vfs::Node *child(char const *name) override { return nullptr; }
-};
-
-
-class Vfs::Lxip_address_file final : public Vfs::File
-{
- private:
-
- unsigned int &_numeric_address;
-
- public:
-
- Lxip_address_file(char const *name, unsigned int &numeric_address)
- : Vfs::File(name), _numeric_address(numeric_address) { }
-
- Lxip::ssize_t read(Lxip_vfs_file_handle &handle,
- Byte_range_ptr const &dst,
- file_size /* ignored */) override
- {
- enum {
- MAX_ADDRESS_STRING_SIZE = sizeof("000.000.000.000\n")
- };
-
- Genode::String address {
- Net::Ipv4_address(&_numeric_address)
- };
-
- Lxip::size_t n = min(dst.num_bytes, strlen(address.string()));
- memcpy(dst.start, address.string(), n);
- if (n < dst.num_bytes)
- dst.start[n++] = '\n';
-
- return n;
- }
-};
-
-
-class Vfs::Lxip_link_state_file final : public Vfs::File
-{
- private:
-
- bool &_numeric_link_state;
-
- public:
-
- Lxip_link_state_file(char const *name, bool &numeric_link_state)
- : Vfs::File(name), _numeric_link_state(numeric_link_state) { }
-
- Lxip::ssize_t read(Lxip_vfs_file_handle &handle,
- Byte_range_ptr const &dst,
- file_size /* ignored */) override
- {
- enum {
- MAX_LINK_STATE_STRING_SIZE = sizeof("down\n")
- };
-
- Genode::String link_state {
- _numeric_link_state ? "up" : "down"
- };
-
- Lxip::size_t n = min(dst.num_bytes, strlen(link_state.string()));
- memcpy(dst.start, link_state.string(), n);
- if (n < dst.num_bytes)
- dst.start[n++] = '\n';
-
- return n;
- }
-};
-
-
-extern "C" unsigned int ic_myaddr;
-extern "C" unsigned int ic_netmask;
-extern "C" unsigned int ic_gateway;
-extern "C" unsigned int ic_nameservers[1];
-
-extern bool ic_link_state;
-
-
-/*******************************
- ** Filesystem implementation **
- *******************************/
-
-class Vfs::Lxip_file_system : public Vfs::File_system,
- public Vfs::Directory
-{
- private:
-
- Genode::Entrypoint &_ep;
- Genode::Allocator &_alloc;
-
- Lxip::Protocol_dir_impl _tcp_dir {
- _alloc, *this, "tcp", Lxip::Protocol_dir::TYPE_STREAM };
- Lxip::Protocol_dir_impl _udp_dir {
- _alloc, *this, "udp", Lxip::Protocol_dir::TYPE_DGRAM };
-
- Lxip_address_file _address { "address", ic_myaddr };
- Lxip_address_file _netmask { "netmask", ic_netmask };
- Lxip_address_file _gateway { "gateway", ic_gateway };
- Lxip_address_file _nameserver { "nameserver", ic_nameservers[0] };
- Lxip_link_state_file _link_state { "link_state", ic_link_state };
-
- Vfs::Node *_lookup(char const *path)
- {
- if (*path == '/') path++;
- if (*path == '\0') return this;
-
- if (Genode::strcmp(path, "tcp", 3) == 0)
- return _tcp_dir.lookup(&path[3]);
-
- if (Genode::strcmp(path, "udp", 3) == 0)
- return _udp_dir.lookup(&path[3]);
-
- if (Genode::strcmp(path, _address.name(),
- strlen(_address.name()) + 1) == 0)
- return &_address;
-
- if (Genode::strcmp(path, _netmask.name(),
- strlen(_netmask.name()) + 1) == 0)
- return &_netmask;
-
- if (Genode::strcmp(path, _gateway.name(),
- strlen(_gateway.name()) + 1) == 0)
- return &_gateway;
-
- if (Genode::strcmp(path, _nameserver.name(),
- strlen(_nameserver.name()) + 1) == 0)
- return &_nameserver;
-
- if (Genode::strcmp(path, _link_state.name(),
- strlen(_link_state.name()) + 1) == 0)
- return &_link_state;
-
- return nullptr;
- }
-
- bool _is_root(const char *path)
- {
- return (strcmp(path, "") == 0) || (strcmp(path, "/") == 0);
- }
-
- Read_result _read(Vfs::Vfs_handle *vfs_handle, Byte_range_ptr const &dst,
- size_t &out_count)
- {
- Vfs::Lxip_vfs_handle *handle =
- static_cast(vfs_handle);
-
- return handle->read(dst, out_count);
- }
-
- public:
-
- Lxip_file_system(Vfs::Env &env, Genode::Xml_node config)
- :
- Directory(""),
- _ep(env.env().ep()), _alloc(env.alloc())
- {
- apply_config(config);
- }
-
- ~Lxip_file_system() { }
-
- char const *name() { return "lxip"; }
- char const *type() override { return "lxip"; }
-
- /***************************
- ** File_system interface **
- ***************************/
-
- void apply_config(Genode::Xml_node const &config) override
- {
- typedef String<16> Addr;
-
- unsigned const mtu = config.attribute_value("mtu", 0U);
- if (mtu) {
- log("Setting MTU to ", mtu);
- lxip_configure_mtu(mtu);
- } else {
- lxip_configure_mtu(0);
- }
-
- if (config.attribute_value("dhcp", false)) {
- log("Using DHCP for interface configuration.");
- lxip_configure_dhcp();
- return;
- }
-
- try {
-
- Addr ip_addr = config.attribute_value("ip_addr", Addr());
- Addr netmask = config.attribute_value("netmask", Addr());
- Addr gateway = config.attribute_value("gateway", Addr());
- Addr nameserver = config.attribute_value("nameserver", Addr());
-
- if (ip_addr == "") {
- warning("Missing \"ip_addr\" attribute. Ignoring network interface config.");
- throw Genode::Xml_node::Nonexistent_attribute();
- } else if (netmask == "") {
- warning("Missing \"netmask\" attribute. Ignoring network interface config.");
- throw Genode::Xml_node::Nonexistent_attribute();
- }
-
- log("static network interface: ip_addr=",ip_addr," netmask=",netmask);
-
- lxip_configure_static(ip_addr.string(), netmask.string(),
- gateway.string(), nameserver.string());
- } catch (...) { }
- }
-
-
- /*************************
- ** Directory interface **
- *************************/
-
- file_size num_dirent() override { return 7; }
-
- Vfs::Directory::Open_result
- open(Vfs::File_system &fs,
- Genode::Allocator &alloc,
- char const*, unsigned, Vfs::Vfs_handle**) override {
- return Vfs::Directory::Open_result::OPEN_ERR_UNACCESSIBLE; }
-
- Lxip::ssize_t read(Byte_range_ptr const &dst, file_size seek_offset) override
- {
- if (dst.num_bytes < sizeof(Dirent))
- return -1;
-
- file_size const index = seek_offset / sizeof(Dirent);
-
- struct Entry
- {
- void const *fileno;
- Dirent_type type;
- char const *name;
- };
-
- enum { NUM_ENTRIES = 8U };
- static Entry const entries[NUM_ENTRIES] = {
- { &_tcp_dir, Dirent_type::DIRECTORY, "tcp" },
- { &_udp_dir, Dirent_type::DIRECTORY, "udp" },
- { &_address, Dirent_type::TRANSACTIONAL_FILE, "address" },
- { &_netmask, Dirent_type::TRANSACTIONAL_FILE, "netmask" },
- { &_gateway, Dirent_type::TRANSACTIONAL_FILE, "gateway" },
- { &_nameserver, Dirent_type::TRANSACTIONAL_FILE, "nameserver" },
- { &_link_state, Dirent_type::TRANSACTIONAL_FILE, "link_state" },
- { nullptr, Dirent_type::END, "" }
- };
-
- Entry const &entry = entries[min(index, NUM_ENTRIES - 1U)];
-
- Dirent &out = *(Dirent*)dst.start;
-
- out = {
- .fileno = (Genode::addr_t)entry.fileno,
- .type = entry.type,
- .rwx = entry.type == Dirent_type::DIRECTORY
- ? Node_rwx::rwx() : Node_rwx::rw(),
- .name = { entry.name }
- };
- return sizeof(Dirent);
- }
-
- Vfs::Node *child(char const *name) override { return nullptr; }
-
- /*********************************
- ** Directory-service interface **
- *********************************/
-
- Dataspace_capability dataspace(char const *path) override {
- return Dataspace_capability(); }
-
- void release(char const *path, Dataspace_capability ds_cap) override { }
-
- Stat_result stat(char const *path, Stat &out) override
- {
- Node *node = _lookup(path);
- if (!node) return STAT_ERR_NO_ENTRY;
-
- out = { };
-
- if (dynamic_cast(node)) {
- out.type = Node_type::DIRECTORY;
- out.rwx = Node_rwx::rwx();
- out.size = 1;
- return STAT_OK;
- }
-
- if (dynamic_cast(node)) {
- out.type = Node_type::CONTINUOUS_FILE;
- out.rwx = Node_rwx::rw();
- out.size = 0;
- return STAT_OK;
- }
-
- if (dynamic_cast(node)) {
- out.type = Node_type::CONTINUOUS_FILE;
- out.rwx = Node_rwx::rw();
- out.size = 0;
- return STAT_OK;
- }
-
- if (dynamic_cast(node)) {
- out.type = Node_type::TRANSACTIONAL_FILE;
- out.rwx = Node_rwx::rw();
- out.size = 0x1000; /* there may be something to read */
- return STAT_OK;
- }
-
- return STAT_ERR_NO_ENTRY;
- }
-
- file_size num_dirent(char const *path) override
- {
- if (_is_root(path)) return num_dirent();
-
- Vfs::Node *node = _lookup(path);
- if (!node) return 0;
-
- Vfs::Directory *dir = dynamic_cast(node);
- if (!dir) return 0;
-
- return dir->num_dirent();
- }
-
- bool directory(char const *path) override
- {
- Vfs::Node *node = _lookup(path);
- return node ? dynamic_cast(node) : 0;
- }
-
- char const *leaf_path(char const *path) override
- {
- Vfs::Node *node = _lookup(path);
- return node ? path : nullptr;
- }
-
- Vfs::Directory_service::Open_result
- open(char const *path, unsigned mode,
- Vfs_handle **out_handle,
- Genode::Allocator &alloc) override
- {
- if (mode & OPEN_MODE_CREATE) return OPEN_ERR_NO_PERM;
-
- try {
- if (Genode::strcmp(path, "/tcp", 4) == 0)
- return _tcp_dir.open(*this, alloc,
- &path[4], mode, out_handle);
- if (Genode::strcmp(path, "/udp", 4) == 0)
- return _udp_dir.open(*this, alloc,
- &path[4], mode, out_handle);
-
- Vfs::Node *node = _lookup(path);
- if (!node) return OPEN_ERR_UNACCESSIBLE;
-
- Vfs::File *file = dynamic_cast(node);
- if (file) {
- Lxip_vfs_file_handle *handle =
- new (alloc) Vfs::Lxip_vfs_file_handle(*this, alloc, 0, file);
- *out_handle = handle;
- return OPEN_OK;
- }
- }
- catch (Genode::Out_of_ram ) { return OPEN_ERR_OUT_OF_RAM; }
- catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
-
- return OPEN_ERR_UNACCESSIBLE;
- }
-
- Opendir_result opendir(char const *path, bool create,
- Vfs_handle **out_handle, Allocator &alloc) override
- {
- Vfs::Node *node = _lookup(path);
-
- if (!node) return OPENDIR_ERR_LOOKUP_FAILED;
-
- Vfs::Directory *dir = dynamic_cast(node);
- if (dir) {
- Lxip_vfs_dir_handle *handle =
- new (alloc) Vfs::Lxip_vfs_dir_handle(*this, alloc, 0, *dir);
- *out_handle = handle;
-
- return OPENDIR_OK;
- }
-
- return OPENDIR_ERR_LOOKUP_FAILED;
- }
-
- void close(Vfs_handle *vfs_handle) override
- {
- Lxip_vfs_handle *handle =
- static_cast(vfs_handle);
-
- Lxip_vfs_file_handle *file_handle =
- dynamic_cast(handle);
-
- if (file_handle)
- _read_ready_waiters_ptr->remove(file_handle->read_ready_elem);
-
- Genode::destroy(handle->alloc(), handle);
- }
-
- Unlink_result unlink(char const *path) override
- {
- if (*path == '/') path++;
-
- if (Genode::strcmp(path, "tcp", 3) == 0)
- return _tcp_dir.unlink(&path[3]);
- if (Genode::strcmp(path, "udp", 3) == 0)
- return _udp_dir.unlink(&path[3]);
- return UNLINK_ERR_NO_ENTRY;
- }
-
- Rename_result rename(char const *, char const *) override {
- return RENAME_ERR_NO_PERM; }
-
- /*************************************
- ** Lxip_file I/O service interface **
- *************************************/
-
- Write_result write(Vfs_handle *vfs_handle,
- Vfs::Const_byte_range_ptr const &src,
- size_t &out_count) override
- {
- Vfs::Lxip_vfs_handle *handle =
- static_cast(vfs_handle);
-
- try { return handle->write(src, out_count); }
- catch (File::Would_block) { return WRITE_ERR_WOULD_BLOCK; }
-
- }
-
- Read_result complete_read(Vfs_handle *vfs_handle,
- Vfs::Byte_range_ptr const &dst,
- size_t &out_count) override
- {
- try { return _read(vfs_handle, dst, out_count); }
- catch (File::Would_block) { return READ_QUEUED; }
- }
-
- Ftruncate_result ftruncate(Vfs_handle *vfs_handle, file_size) override
- {
- /* report ok because libc always executes ftruncate() when opening rw */
- return FTRUNCATE_OK;
- }
-
- bool notify_read_ready(Vfs_handle *vfs_handle) override
- {
- Lxip_vfs_file_handle *handle =
- dynamic_cast(vfs_handle);
-
- if (handle) {
- if (!handle->read_ready_elem.enqueued())
- _read_ready_waiters_ptr->enqueue(handle->read_ready_elem);
- return true;
- }
-
- return false;
- }
-
- bool read_ready(Vfs_handle const &vfs_handle) const override
- {
- Lxip_vfs_handle const &handle =
- static_cast(vfs_handle);
-
- return handle.read_ready();
- }
-
- bool write_ready(Vfs_handle const &vfs_handle) const override
- {
- /* wakeup from WRITE_ERR_WOULD_BLOCK not supported */
- return true;
- }
-
- Sync_result complete_sync(Vfs_handle *vfs_handle)
- {
- Vfs::Lxip_vfs_handle *handle =
- static_cast(vfs_handle);
- return handle->sync();
- }
-};
-
-
-struct Lxip_factory : Vfs::File_system_factory
-{
- struct Init
- {
- char _config_buf[128];
-
- char *_parse_config(Genode::Xml_node);
-
- Timer::Connection timer;
-
- Init(Genode::Env &env,
- Genode::Allocator &alloc)
- : timer(env, "vfs_lxip")
- {
- Lx_kit::Env &lx_env = Lx_kit::construct_env(env);
-
- Lx::lxcc_emul_init(lx_env);
- Lx::malloc_init(env, lx_env.heap());
- Lx::timer_init(env.ep(), timer, lx_env.heap(), &poll_all);
- Lx::nic_client_init(env, lx_env.heap(), &poll_all);
-
- lxip_init();
- }
- };
-
- Vfs::File_system *create(Vfs::Env &env, Genode::Xml_node config) override
- {
- _vfs_user_ptr = &env.user();
- static Init inst(env.env(), env.alloc());
- return new (env.alloc()) Vfs::Lxip_file_system(env, config);
- }
-};
-
-
-extern "C" Vfs::File_system_factory *vfs_file_system_factory(void)
-{
- static Vfs::Lxip_vfs_file_handle::Fifo read_ready_waiters;
-
- _read_ready_waiters_ptr = &read_ready_waiters;
-
- static Lxip_factory factory;
- return &factory;
-}