dde_linux: port of WireGuard kernel module

A userland component that ports the Linux WireGuard kernel module (originally
from kernel version 5.14.21) and integrates it via a NIC session (public
network side) and an Uplink session (private network side). The
WireGuard-specific device configuration is done through the component
configuration. The port is done using lx_emul, lx_kit and the virt_linux
targets. The commit adds also 4 corresponding run scripts of which 3 are fully
automated of which 1 is added to the autopilot.

:Warning:

Although in principal functioning, the WireGuard port has not been exposed to a
sufficient amount of real-world testing, so far. Therefore, we strongly
recommend not to use it in any security-critical scenarios! There is no
guarantee that the port meets any of the security goals pursued by the
WireGuard protocol or other WireGuard implementations!

Ref #4397
This commit is contained in:
Martin Stein 2022-05-18 12:34:23 +02:00 committed by Christian Helmuth
parent f84e512ded
commit a845dffa63
57 changed files with 7378 additions and 0 deletions

View File

@ -0,0 +1,23 @@
#
# For documentation see $(REP_DIR)/lib/mk/wireguard.inc .
#
PRG_DIR := $(REP_DIR)/src/app/wireguard/spec/arm_64
GEN_PRG_DIR := $(PRG_DIR)/../..
SRC_C += arch/arm64/kernel/smp.c
SRC_C += kernel/smp.c
SRC_C += arch/arm64/kernel/cpufeature.c
vpath arch/arm64/kernel/cpufeature.c $(GEN_PRG_DIR)/lx_emul/shadow
vpath arch/arm64/kernel/smp.c $(REP_DIR)/src/lib/lx_emul/shadow
vpath kernel/smp.c $(REP_DIR)/src/lib/lx_emul/shadow
SRC_S += arch/arm64/crypto/poly1305-core.S
arch/arm64/crypto/poly1305-core.S:
$(VERBOSE)perl $(LX_SRC_DIR)/arch/arm64/crypto/poly1305-armv8.pl > $@
CC_OPT_arch/arm64/crypto/poly1305-core += -Dpoly1305_init=poly1305_init_arm64
include $(REP_DIR)/lib/mk/wireguard.inc

View File

@ -0,0 +1,12 @@
#
# For documentation see $(REP_DIR)/lib/mk/wireguard.inc .
#
PRG_DIR := $(REP_DIR)/src/app/wireguard/spec/x86_64
SRC_S += arch/x86/crypto/poly1305-x86_64-cryptogams.S
arch/x86/crypto/poly1305-x86_64-cryptogams.S:
perl $(LX_SRC_DIR)/arch/x86/crypto/poly1305-x86_64-cryptogams.pl > $@
include $(REP_DIR)/lib/mk/wireguard.inc

View File

@ -0,0 +1,61 @@
#
# This library is for avoiding clashes between Linux and Genode includes.
# If we were to compile all the *.c files of this library directly with the
# Wireguard target there would be only one INC_DIR applied to *.cc files as
# well as to *.c files. Some Genode headers, however (e.g. 'net/udp.h' or
# 'net/dhcp.h') exist with the same include identifier in both Linux and
# Genode, and we would have the problem that we want the Linux variant in *.c
# files and the Genode variant in *.cc files. Therefore, we create two
# dedicated INC_DIR settings (that of the library and that of the target).
#
GEN_PRG_DIR := $(PRG_DIR)/../..
SRC_C += $(notdir $(wildcard $(PRG_DIR)/generated_dummies.c))
SRC_C += dummies.c
SRC_C += dummies_arch.c
SRC_C += lx_emul.c
SRC_C += wireguard.c
SRC_C += genode_c_api_arch.c
vpath lx_emul/alloc.cc $(GEN_PRG_DIR)
vpath lx_kit/memory.cc $(GEN_PRG_DIR)
vpath wireguard.c $(GEN_PRG_DIR)/genode_c_api
vpath %.c $(PRG_DIR)
vpath %.c $(GEN_PRG_DIR)
INC_DIR += $(PRG_DIR)
INC_DIR += $(GEN_PRG_DIR)
LIBS += lx_emul virt_linux_generated
CC_OPT_wireguard += -DKBUILD_MODFILE='"wireguard"' \
-DKBUILD_BASENAME='"wireguard"' \
-DKBUILD_MODNAME='"wireguard"'
CC_OPT_lx_emul += -DKBUILD_MODFILE='"lx_emul"' \
-DKBUILD_BASENAME='"lx_emul"' \
-DKBUILD_MODNAME='"lx_emul"'
#
# The lx_emul Makefiles have a generic mechanism for defining the
# KBUILD_MODNAME for each Linux unit to be the filename of that unit
# (without suffix). However, some Wireguard units expect
# KBUILD_MODNAME to be the same for all Wireguard units.
# Therefore, we do a pattern substition on the CC_OPT_* variables of
# those units, changing their KBUILD_MODNAME def to "wireguard".
#
OBJECTS_TO_FIX_MODNAME_DEFS_FOR := \
drivers/net/wireguard/device.o \
drivers/net/wireguard/netlink.o
define FIX_MODNAME_DEF =
CC_OPT_$(1) = $(patsubst -DKBUILD_MODNAME='"%"',-DKBUILD_MODNAME='"wireguard"',$(CC_OPT_$(1)))
endef
.PHONY: fix_modname_defs
fix_modname_defs:
$(foreach file,$(OBJECTS_TO_FIX_MODNAME_DEFS_FOR), \
$(eval $(call FIX_MODNAME_DEF,$(file:%.o=%))))
$(OBJECTS_TO_FIX_MODNAME_DEFS_FOR): fix_modname_defs

View File

@ -0,0 +1,419 @@
#
# FetchURL downloading a file from a LightTPD server through a Wireguard VPN
#
# By default, the file is an short inline HTML file at lighttpd and downloaded
# into RAM in fetchurl. However, when the test is run with base-linux,
# lighttpd uses a file created by the host filled filled with zeroes and of
# customizable size and fetchurl downloads into the host FS, so the test can
# then check the MD5 sum of the file.
#
if {[expr ![have_spec arm_64] && ![have_spec x86_64]]} {
puts "Run script is not supported on this platform."
exit 0
}
if {[have_spec linux]} {
set linux 1
set not_linux 0
} else {
set linux 0
set not_linux 1
}
#
# Note that in the not_linux case, the file size is rounded
# down to a multiple of 100.
#
set file_size_in_bytes 1000000
create_boot_directory
import_from_depot [depot_user]/src/libc \
[depot_user]/src/libssh \
[depot_user]/src/lighttpd \
[depot_user]/src/openssl \
[depot_user]/src/posix \
[depot_user]/src/vfs \
[depot_user]/src/vfs_lwip \
[depot_user]/src/zlib
append config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
</parent-provides>
<start name="timer" caps="100">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
<route>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="report" caps="100">
<binary name="report_rom"/>
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<route>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start> }
append_if $linux config {
<start name="lx_fs" ld="no" caps="1000">
<resource name="RAM" quantum="4M"/>
<provides> <service name="File_system"/> </provides>
<config>
<policy label_prefix="fetchurl" root="/fetchurl_fs/" writeable="yes"/>
<policy label_prefix="lighttpd" root="/lighttpd_fs/" writeable="yes"/>
</config>
<route>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start> }
append config {
<start name="fetchurl" caps="300">
<resource name="RAM" quantum="50M"/>
<config>
<report progress="yes"/>
<vfs>
<dir name="dev">
<log/> <null/>
<inline name="rtc">2019-07-04 12:00</inline>
<inline name="random">01234567890123456789</inline>
</dir>
<dir name="socket">
<lwip dhcp="yes"/>
</dir>
<dir name="vm"> }
append_if $linux config {
<fs/> }
append_if $not_linux config {
<ram/> }
append config {
</dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc" socket="/socket"/>
<fetch url="10.0.9.2" path="/vm/index.html" retry="3"/>
</config>
<route>
<service name="File_system"> <child name="lx_fs"/> </service>
<service name="Report"> <child name="report"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="Nic"> <child name="nic_router"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="peer1_wireguard" caps="200">
<binary name="wireguard"/>
<resource name="RAM" quantum="10M"/>
<config private_key="0CtU34qsl97IGiYKSO4tMaF/SJvy04zzeQkhZEbZSk0="
listen_port="49001">
<peer public_key="GrvyALPZ3PQ2AWM+ovxJqnxSqKpmTyqUui5jH+C8I0E="
endpoint_ip="10.1.2.1"
endpoint_port="49002"
allowed_ip="10.0.9.2/32" />
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="Nic"> <child name="nic_router"/> </service>
<service name="Uplink"> <child name="nic_router"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="nic_router" caps="200">
<resource name="RAM" quantum="10M"/>
<provides>
<service name="Nic"/>
<service name="Uplink"/>
</provides>
<config>
<policy label="peer1_wireguard -> nic_session" domain="peer1_outer_downlink"/>
<policy label="peer1_wireguard -> uplink_session" domain="peer1_inner_uplink"/>
<policy label="fetchurl -> lwip" domain="peer1_inner_downlink"/>
<policy label="peer2_wireguard -> nic_session" domain="peer2_outer_downlink"/>
<policy label="peer2_wireguard -> uplink_session" domain="peer2_inner_uplink"/>
<policy label="lighttpd -> lwip" domain="peer2_inner_downlink"/>
<domain name="peer1_outer_downlink" interface="10.1.2.1/24">
<dhcp-server ip_first="10.1.2.2" ip_last="10.1.2.2"/>
<udp-forward port="49002" domain="peer2_outer_downlink" to="10.0.3.2"/>
</domain>
<domain name="peer1_inner_uplink" interface="10.0.9.1/24" use_arp="no" >
<nat domain="peer1_inner_downlink" tcp-ports="1000"/>
</domain>
<domain name="peer1_inner_downlink" interface="10.1.3.1/24">
<dhcp-server ip_first="10.1.3.2" ip_last="10.1.3.2"/>
<tcp dst="10.0.9.2/24">
<permit port="80" domain="peer1_inner_uplink"/>
</tcp>
</domain>
<domain name="peer2_outer_downlink" interface="10.0.3.1/24">
<dhcp-server ip_first="10.0.3.2" ip_last="10.0.3.2"/>
</domain>
<domain name="peer2_inner_uplink" interface="10.0.9.2/24" use_arp="no">
<tcp-forward port="80" domain="peer2_inner_downlink" to="10.0.5.2"/>
</domain>
<domain name="peer2_inner_downlink" interface="10.0.5.1/24">
<dhcp-server ip_first="10.0.5.2" ip_last="10.0.5.2"/>
</domain>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="peer2_wireguard" caps="200">
<binary name="wireguard"/>
<resource name="RAM" quantum="10M"/>
<config private_key="8GRSQZMgG1uuvz4APIBqrDmiLj8L886r++hzixjjHFc="
listen_port="49002">
<peer public_key="r1Gslnm82X8NaijsWzPoSFzDZGl2tTJoPa+EJL4gYQw="
allowed_ip="10.0.9.1/32" />
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="Nic"> <child name="nic_router"/> </service>
<service name="Uplink"> <child name="nic_router"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="lighttpd" caps="200">
<resource name="RAM" quantum="50M" />
<config>
<arg value="lighttpd" />
<arg value="-f" />
<arg value="/etc/lighttpd/lighttpd.conf" />
<arg value="-D" />
<vfs>
<dir name="dev">
<log/> <null/>
<inline name="rtc">2000-01-01 00:00</inline>
<inline name="random">0123456789012345678901234567890123456789</inline>
</dir>
<dir name="socket"> <lwip dhcp="yes"/> </dir>
<dir name="etc">
<dir name="lighttpd">
<inline name="lighttpd.conf">
# lighttpd configuration
server.port = 80
server.document-root = "/website"
server.event-handler = "select"
server.network-backend = "write"
server.upload-dirs = ( "/tmp" )
server.modules = ("mod_openssl")
index-file.names = (
"index.xhtml", "index.html", "index.htm"
)
mimetype.assign = (
".html" => "text/html",
".htm" => "text/html"
)
$SERVER["socket"] == ":443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/lighttpd/example.pem"
}
</inline>
<inline name="example.pem">
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC4KHUZjDRew89c
wDlYPz9XFigcMDnDlHzdg2ByrGZIOUNYC5LH1QUK0TDbPP45Xx455niA0QY85dMQ
4DQx0Qk6+TDpVD3F2MYQgbIX6YkX9kgqX+jiHgsNzRD4KamNYmfUY+dJhlZEXWAF
uNSnRLvg4EH72AVKLLKiruGwkisW/AYU6dNE8iFOYL8Q75bBUADiQSDdD8vkpeXg
1NqxNyHPR6YRbA+vqcK0kbC8btKR9wG6m99OhTR4x3M87vtFFLNtJNEf54fYxi+L
1rljSqHbaXD+XJsVKgX+UlI1ZlYW4KqlMciMemkBp0CovCxLfsbMmkXAW2RONpkm
+sdO3CXFAgMBAAECggEAIKv00nqAVAuzP0ZPJivaZe3lYdLgfKVcXcRQGSgi4U9f
dkBfYxqU0W15mHvCspUAfM85s8jhrW4suwK739axJ4hMOCkc6Hvj78vCt+FT1C96
cCIh4/PmjCVEjHJ/xTifKRwsTWwK5AgY4AsBl0dneabvremOTrGNY7VZDwVvpZz1
qXkSNjQ63tZKj9cESO5ceGLzuBAG6JDDpqJM5fmdsQ36/QVz9Gogr8bXEWFM1TOo
lWVAPB/l6nqKurfMv+5th354+owv9CGKxqLBE1fujwE2VogBz7mkR/rnABOPU5ev
wQVLXoUkO2bI8Uvc28lChaiG6ihfdmNCmwoi56HFRQKBgQDj0WoIxiY7H42KV7Hh
uQZv/0aoQyjXuqJ7Vq0HdxOAxZr0GpSYgo3MTZWooI2AnAstPHXo0BsQr+XVijWm
xiDxMM4p9nrBzjEIHwyDaf62Pz/6lIPdenynLiEIOUbocJ3r0/3tCrY3U7fgjzYY
f9PZmXKEOOKdbVPyXG0OIJ/ADwKBgQDO8GkCdVGy/YB0X7ntqcBG0xgmDnKRmYpQ
X7Tb377AT2lzvftxaRVrx+UXtvFdy4xdrxjqHJCgOHT/fsAfjJlo7v1+KhTvE0pt
jCdJPLbzXJRwaISaeEaMJ/N8Vv/j2/YuoS5M5vh4NlWeO16HtF7N9V9cMEZ5iRW1
9G/eWgOo6wKBgQCY6rn3xblnuhgxogd+ccmGZ50v2FST6WyiyV0/Q4hNyVXnP+g6
LneriPBJzertRtChvpGOghGIs+jb2veESD1YZ+Aafp2LdTGoN98YXo9gGTiCpCmX
Al6lgOsfMAMOhnkaEKPC9ou0u3cTPk2bSEIVL1CUu/IwpW/RoIR7FR7ltQKBgQDA
RAmsqQfhPzqL5SzALclhhFuZcC7uLDOf/WvyJW37C000pjzp3/JxE2Y8pFKZDLc7
i6WgTi3pTssVXtRt+5nFLtcC02Jjxg6OvXr6xphMf6XC0rjxM/KH4c6Npd9V+1Y9
eK+l76rHNeRSgWKQvvqebO3On2O7I6yyQ4t0kTl5RQKBgQCbX1cTtNmNr6HNleXL
zfclKESSYy57uq3fQxhRrEE2ZNbemLOxEuoBCFYoMwpZEjC1GZyICrM7o5673/Ih
I0oZerUBmt2l8noZCQoITEa97bCbp2vIdHYnCf/H3Nf2qM329fc00kAmm7vUVRgM
4BqXnuFcAOuY68sgp9JArzK+EQ==
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUYPOYXijLmMjjlgRCGHuZeyP0iPEwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCREUxEzARBgNVBAgMClNvbWUtU3RhdGUxDTALBgNVBAoM
BFRlc3QxEjAQBgNVBAMMCTEwLjAuMi41NTAeFw0yMDA1MTQxNDQ0MzlaFw00NzA5
MzAxNDQ0MzlaMEUxCzAJBgNVBAYTAkRFMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0w
CwYDVQQKDARUZXN0MRIwEAYDVQQDDAkxMC4wLjIuNTUwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQC4KHUZjDRew89cwDlYPz9XFigcMDnDlHzdg2ByrGZI
OUNYC5LH1QUK0TDbPP45Xx455niA0QY85dMQ4DQx0Qk6+TDpVD3F2MYQgbIX6YkX
9kgqX+jiHgsNzRD4KamNYmfUY+dJhlZEXWAFuNSnRLvg4EH72AVKLLKiruGwkisW
/AYU6dNE8iFOYL8Q75bBUADiQSDdD8vkpeXg1NqxNyHPR6YRbA+vqcK0kbC8btKR
9wG6m99OhTR4x3M87vtFFLNtJNEf54fYxi+L1rljSqHbaXD+XJsVKgX+UlI1ZlYW
4KqlMciMemkBp0CovCxLfsbMmkXAW2RONpkm+sdO3CXFAgMBAAGjUzBRMB0GA1Ud
DgQWBBQvSHuosL/SDn/8sKl0dpyPeFvOfjAfBgNVHSMEGDAWgBQvSHuosL/SDn/8
sKl0dpyPeFvOfjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBR
sGYEuRwIU/tmAmTbniptItN9VE0NNj9QeKh+hKQ9cHvhxmlBlf5b7Vb2JaRZdy88
kRIFKiNkyjgQVg+5KuEIcg17mHSal7zG+jIZ3c1bIpVCM4AjUe7EXl8LM4+dJ5sX
Bwpd34tUk2edOiT8R/dU7uesxCdeIQ2FfvKyrXca73nj+UTvFGXUk/9mWY8KAaYc
F/PWBhiZhJD4/dkUHJnrVtjpcqW2Io8bFmrMq2vfqQv+W2FZGCsHgXkAZO2E0jyQ
5eOrwzgWRtMc5PvoGvqQfefseaLs0fvSQdcPqfv88Eqk5NGTOCIW8/KEsBwFJuwa
EpA5DBBklj8UE2CdONvN
-----END CERTIFICATE-----
</inline>
</dir>
</dir>
<dir name="website"> }
append_if $linux config {
<fs/> }
if {$not_linux} {
append config {<inline name="index.html">}
for {set i 0} {$i < $file_size_in_bytes} {incr i 64} {
# append 100 bytes of "0"
append config {0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
}
append config {</inline>}
}
append config {
</dir>
<dir name="tmp"> <ram/> </dir>
</vfs>
<libc stdin="/dev/null" stdout="/dev/log" stderr="/dev/log"
rtc="/dev/rtc" rng="/dev/random" socket="/socket"/>
</config>
<route>
<service name="File_system"> <child name="lx_fs"/> </service>
<service name="Nic"> <child name="nic_router"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
</config>
}
install_config $config
append targets {
core init timer server/nic_router app/wireguard server/report_rom
app/fetchurl }
append boot_modules {
core init timer nic_router wireguard fetchurl report_rom curl.lib.so
ld.lib.so }
if $linux {
append targets { server/lx_fs }
append boot_modules { lx_fs }
# create the lx_fs root of fetchurl where it will store the downloaded file
proc lx_fs_root {} { return [run_dir]/genode }
exec rm -rf [lx_fs_root]/fetchurl_fs
exec mkdir -p [lx_fs_root]/fetchurl_fs
# create the lx_fs root of lighttpd and the downloadable file inside it
exec rm -rf [lx_fs_root]/lighttpd_fs
exec mkdir -p [lx_fs_root]/lighttpd_fs
exec head -c $file_size_in_bytes /dev/zero > [lx_fs_root]/lighttpd_fs/index.html
}
build $targets
build_boot_image $boot_modules
append qemu_args "-nographic "
# run the scenario till fetchurl succeeded to download the file
run_genode_until "fetchurl. exited with exit value 0.*\n" 60
if {$linux} {
# check that the md5 sum of the downloaded file is correct
set lighttpd_index_md5 [exec md5sum [lx_fs_root]/lighttpd_fs/index.html]
set fetchurl_index_md5 [exec md5sum [lx_fs_root]/fetchurl_fs/index.html]
puts ""
puts $lighttpd_index_md5
puts $fetchurl_index_md5
puts "MD5SUM of transferred files is correct"
if {[string compare -length 32 $lighttpd_index_md5 $fetchurl_index_md5]} {
puts ""
puts "Error: MD5SUM of transferred files is incorrect"
puts ""
exit -1
}
}

View File

@ -0,0 +1,293 @@
#
# LightTPD server in a Wireguard VPN
#
# Once the scenario is running and DHCP is done, you can reach the server from
# your host system via 10.0.9.2:80 . The traffic is going through a host
# Wireguard device 'wg0' that puts it into an encrypted UDP tunnel towards the
# TAP device 'tap0' where it enters Qemu and reaches the inner Genode router
# at domain 'uplink'. The inner router port-forwards the traffic to its
# 'downlink' domain to which the tunnel side (10.0.3.2) of the Genode Wireguard
# component is connected . This component unpacks the original packets
# from the tunnel. The back side of the component is connected to the inner
# Genode router at domain 'uplink' and sends the plain packets unmodified a
# this connection. The routers IP identity in that domain is the Wireguard
# device IP, speak the VPN-internal IP 10.0.9.2 of the server. The inner
# router now forwards the different ports to the corresponding peers, in
# this case TCP port 80 to the LightTPD server (10.0.5.2) at the inner
# router domain "downlink".
#
source ${genode_dir}/repos/dde_linux/run/wg_qemu_tap_preamble.inc
create_boot_directory
import_from_depot [depot_user]/src/[base_src] \
[depot_user]/pkg/[drivers_nic_pkg] \
[depot_user]/src/init \
[depot_user]/src/nic_router \
[depot_user]/src/libc \
[depot_user]/src/libssh \
[depot_user]/src/lighttpd \
[depot_user]/src/openssl \
[depot_user]/src/posix \
[depot_user]/src/vfs \
[depot_user]/src/vfs_lwip \
[depot_user]/src/zlib
install_config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
</parent-provides>
<start name="timer" caps="100">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
<route>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="drivers" caps="1000" managing_system="yes">
<resource name="RAM" quantum="32M"/>
<binary name="init"/>
<route>
<service name="ROM" label="config">
<parent label="drivers.config"/>
</service>
<service name="Timer"> <child name="timer"/> </service>
<service name="Uplink"> <child name="outer_router"/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="outer_router" caps="200">
<binary name="nic_router"/>
<resource name="RAM" quantum="10M"/>
<provides>
<service name="Nic"/>
<service name="Uplink"/>
</provides>
<config verbose_domain_state="yes" dhcp_discover_timeout_sec="1">
<policy label_prefix="drivers" domain="uplink"/>
<policy label="wireguard -> nic_session" domain="downlink"/>
<domain name="uplink">
<udp-forward port="49002" domain="downlink" to="10.0.3.2"/>
</domain>
<domain name="downlink" interface="10.0.3.1/24">
<dhcp-server ip_first="10.0.3.2"
ip_last="10.0.3.2"
dns_config_from="uplink"/>
</domain>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="inner_router" caps="200">
<binary name="nic_router"/>
<resource name="RAM" quantum="10M"/>
<provides>
<service name="Nic"/>
<service name="Uplink"/>
</provides>
<config verbose_domain_state="yes" dhcp_discover_timeout_sec="1">
<policy label="wireguard -> uplink_session" domain="uplink"/>
<policy label_prefix="lighttpd" domain="downlink"/>
<domain name="uplink" interface="10.0.9.2/24" use_arp="no">
<tcp-forward port="80" domain="downlink" to="10.0.5.2"/>
</domain>
<domain name="downlink" interface="10.0.5.1/24">
<dhcp-server ip_first="10.0.5.2" ip_last="10.0.5.2"/>
</domain>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="wireguard" caps="200">
<resource name="RAM" quantum="10M"/>
<config private_key="8GRSQZMgG1uuvz4APIBqrDmiLj8L886r++hzixjjHFc="
listen_port="49002">
<peer public_key="r1Gslnm82X8NaijsWzPoSFzDZGl2tTJoPa+EJL4gYQw="
allowed_ip="10.0.9.1/32" />
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="Nic"> <child name="outer_router"/> </service>
<service name="Uplink"> <child name="inner_router"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="lighttpd" caps="200">
<resource name="RAM" quantum="1G" />
<config>
<arg value="lighttpd" />
<arg value="-f" />
<arg value="/etc/lighttpd/lighttpd.conf" />
<arg value="-D" />
<vfs>
<dir name="dev">
<log/> <null/>
<inline name="rtc">2000-01-01 00:00</inline>
<inline name="random">0123456789012345678901234567890123456789</inline>
</dir>
<dir name="socket"> <lwip dhcp="yes"/> </dir>
<dir name="etc">
<dir name="lighttpd">
<inline name="lighttpd.conf">
# lighttpd configuration
server.port = 80
server.document-root = "/website"
server.event-handler = "select"
server.network-backend = "write"
server.upload-dirs = ( "/tmp" )
server.modules = ("mod_openssl")
index-file.names = (
"index.xhtml", "index.html", "index.htm"
)
mimetype.assign = (
".html" => "text/html",
".htm" => "text/html"
)
$SERVER["socket"] == ":443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/lighttpd/example.pem"
}
</inline>
<inline name="example.pem">
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC4KHUZjDRew89c
wDlYPz9XFigcMDnDlHzdg2ByrGZIOUNYC5LH1QUK0TDbPP45Xx455niA0QY85dMQ
4DQx0Qk6+TDpVD3F2MYQgbIX6YkX9kgqX+jiHgsNzRD4KamNYmfUY+dJhlZEXWAF
uNSnRLvg4EH72AVKLLKiruGwkisW/AYU6dNE8iFOYL8Q75bBUADiQSDdD8vkpeXg
1NqxNyHPR6YRbA+vqcK0kbC8btKR9wG6m99OhTR4x3M87vtFFLNtJNEf54fYxi+L
1rljSqHbaXD+XJsVKgX+UlI1ZlYW4KqlMciMemkBp0CovCxLfsbMmkXAW2RONpkm
+sdO3CXFAgMBAAECggEAIKv00nqAVAuzP0ZPJivaZe3lYdLgfKVcXcRQGSgi4U9f
dkBfYxqU0W15mHvCspUAfM85s8jhrW4suwK739axJ4hMOCkc6Hvj78vCt+FT1C96
cCIh4/PmjCVEjHJ/xTifKRwsTWwK5AgY4AsBl0dneabvremOTrGNY7VZDwVvpZz1
qXkSNjQ63tZKj9cESO5ceGLzuBAG6JDDpqJM5fmdsQ36/QVz9Gogr8bXEWFM1TOo
lWVAPB/l6nqKurfMv+5th354+owv9CGKxqLBE1fujwE2VogBz7mkR/rnABOPU5ev
wQVLXoUkO2bI8Uvc28lChaiG6ihfdmNCmwoi56HFRQKBgQDj0WoIxiY7H42KV7Hh
uQZv/0aoQyjXuqJ7Vq0HdxOAxZr0GpSYgo3MTZWooI2AnAstPHXo0BsQr+XVijWm
xiDxMM4p9nrBzjEIHwyDaf62Pz/6lIPdenynLiEIOUbocJ3r0/3tCrY3U7fgjzYY
f9PZmXKEOOKdbVPyXG0OIJ/ADwKBgQDO8GkCdVGy/YB0X7ntqcBG0xgmDnKRmYpQ
X7Tb377AT2lzvftxaRVrx+UXtvFdy4xdrxjqHJCgOHT/fsAfjJlo7v1+KhTvE0pt
jCdJPLbzXJRwaISaeEaMJ/N8Vv/j2/YuoS5M5vh4NlWeO16HtF7N9V9cMEZ5iRW1
9G/eWgOo6wKBgQCY6rn3xblnuhgxogd+ccmGZ50v2FST6WyiyV0/Q4hNyVXnP+g6
LneriPBJzertRtChvpGOghGIs+jb2veESD1YZ+Aafp2LdTGoN98YXo9gGTiCpCmX
Al6lgOsfMAMOhnkaEKPC9ou0u3cTPk2bSEIVL1CUu/IwpW/RoIR7FR7ltQKBgQDA
RAmsqQfhPzqL5SzALclhhFuZcC7uLDOf/WvyJW37C000pjzp3/JxE2Y8pFKZDLc7
i6WgTi3pTssVXtRt+5nFLtcC02Jjxg6OvXr6xphMf6XC0rjxM/KH4c6Npd9V+1Y9
eK+l76rHNeRSgWKQvvqebO3On2O7I6yyQ4t0kTl5RQKBgQCbX1cTtNmNr6HNleXL
zfclKESSYy57uq3fQxhRrEE2ZNbemLOxEuoBCFYoMwpZEjC1GZyICrM7o5673/Ih
I0oZerUBmt2l8noZCQoITEa97bCbp2vIdHYnCf/H3Nf2qM329fc00kAmm7vUVRgM
4BqXnuFcAOuY68sgp9JArzK+EQ==
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUYPOYXijLmMjjlgRCGHuZeyP0iPEwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCREUxEzARBgNVBAgMClNvbWUtU3RhdGUxDTALBgNVBAoM
BFRlc3QxEjAQBgNVBAMMCTEwLjAuMi41NTAeFw0yMDA1MTQxNDQ0MzlaFw00NzA5
MzAxNDQ0MzlaMEUxCzAJBgNVBAYTAkRFMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0w
CwYDVQQKDARUZXN0MRIwEAYDVQQDDAkxMC4wLjIuNTUwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQC4KHUZjDRew89cwDlYPz9XFigcMDnDlHzdg2ByrGZI
OUNYC5LH1QUK0TDbPP45Xx455niA0QY85dMQ4DQx0Qk6+TDpVD3F2MYQgbIX6YkX
9kgqX+jiHgsNzRD4KamNYmfUY+dJhlZEXWAFuNSnRLvg4EH72AVKLLKiruGwkisW
/AYU6dNE8iFOYL8Q75bBUADiQSDdD8vkpeXg1NqxNyHPR6YRbA+vqcK0kbC8btKR
9wG6m99OhTR4x3M87vtFFLNtJNEf54fYxi+L1rljSqHbaXD+XJsVKgX+UlI1ZlYW
4KqlMciMemkBp0CovCxLfsbMmkXAW2RONpkm+sdO3CXFAgMBAAGjUzBRMB0GA1Ud
DgQWBBQvSHuosL/SDn/8sKl0dpyPeFvOfjAfBgNVHSMEGDAWgBQvSHuosL/SDn/8
sKl0dpyPeFvOfjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBR
sGYEuRwIU/tmAmTbniptItN9VE0NNj9QeKh+hKQ9cHvhxmlBlf5b7Vb2JaRZdy88
kRIFKiNkyjgQVg+5KuEIcg17mHSal7zG+jIZ3c1bIpVCM4AjUe7EXl8LM4+dJ5sX
Bwpd34tUk2edOiT8R/dU7uesxCdeIQ2FfvKyrXca73nj+UTvFGXUk/9mWY8KAaYc
F/PWBhiZhJD4/dkUHJnrVtjpcqW2Io8bFmrMq2vfqQv+W2FZGCsHgXkAZO2E0jyQ
5eOrwzgWRtMc5PvoGvqQfefseaLs0fvSQdcPqfv88Eqk5NGTOCIW8/KEsBwFJuwa
EpA5DBBklj8UE2CdONvN
-----END CERTIFICATE-----
</inline>
</dir>
</dir>
<dir name="website">
<inline name="index.html">
<html>
<head>
<title>Hello</title>
</head>
<body>
<p>Hello Genode!</p>
<b>I am bold ;-)</b>
</body>
</html>
</inline>
</dir>
<dir name="tmp"> <ram/> </dir>
</vfs>
<libc stdin="/dev/null" stdout="/dev/log" stderr="/dev/log"
rtc="/dev/rtc/" rng="/dev/random" socket="/socket"/>
</config>
<route>
<service name="Nic"> <child name="inner_router"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
</config>
}
build { app/wireguard }
build_boot_image { wireguard }
run_genode_until forever

View File

@ -0,0 +1,161 @@
#
# Let the host Linux ping a Genode in Qemu through a Wireguard tunnel.
#
source ${genode_dir}/repos/dde_linux/run/wg_qemu_tap_preamble.inc
create_boot_directory
import_from_depot [depot_user]/src/[base_src] \
[depot_user]/pkg/[drivers_nic_pkg] \
[depot_user]/src/init \
[depot_user]/src/nic_router
install_config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
</parent-provides>
<start name="timer" caps="100">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
<route>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="drivers" caps="1000" managing_system="yes">
<resource name="RAM" quantum="32M"/>
<binary name="init"/>
<route>
<service name="ROM" label="config">
<parent label="drivers.config"/>
</service>
<service name="Timer"> <child name="timer"/> </service>
<service name="Uplink"> <child name="outer_router"/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="outer_router" caps="200">
<binary name="nic_router"/>
<resource name="RAM" quantum="10M"/>
<provides>
<service name="Nic"/>
<service name="Uplink"/>
</provides>
<config verbose_domain_state="yes" dhcp_discover_timeout_sec="1">
<policy label_prefix="drivers" domain="uplink"/>
<policy label="wireguard -> nic_session" domain="downlink"/>
<domain name="uplink">
<udp-forward port="49002" domain="downlink" to="10.0.3.2"/>
</domain>
<domain name="downlink" interface="10.0.3.1/24"/>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="inner_router" caps="200">
<binary name="nic_router"/>
<resource name="RAM" quantum="10M"/>
<provides>
<service name="Nic"/>
<service name="Uplink"/>
</provides>
<config verbose_domain_state="yes" dhcp_discover_timeout_sec="1">
<policy label="wireguard -> uplink_session" domain="uplink"/>
<domain name="uplink"
interface="10.0.9.2/24"
use_arp="no"
icmp_echo_server="yes"/>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="wireguard" caps="200">
<resource name="RAM" quantum="10M"/>
<config private_key="8GRSQZMgG1uuvz4APIBqrDmiLj8L886r++hzixjjHFc="
interface="10.0.3.2/24"
listen_port="49002">
<peer public_key="r1Gslnm82X8NaijsWzPoSFzDZGl2tTJoPa+EJL4gYQw="
allowed_ip="10.0.9.1/32" />
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="Nic"> <child name="outer_router"/> </service>
<service name="Uplink"> <child name="inner_router"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
</config>
}
build { app/wireguard }
build_boot_image { wireguard }
run_genode_until "uplink\] dynamic IP config: interface 10.0.2.3" 10
set timeout 60
append wait_for_string "64 bytes from 10.0.9.2.*"
append wait_for_string "64 bytes from 10.0.9.2.*"
append wait_for_string "64 bytes from 10.0.9.2.*\n"
eval spawn ping 10.0.9.2
expect {
-re $wait_for_string { }
eof {
puts stderr "Error: Spawned process died unexpectedly";
exit -3
}
timeout {
puts stderr "Error: Test execution timed out";
exit -2
}
}

View File

@ -0,0 +1,172 @@
#
# Let a Genode in Qemu ping the host Linux through a Wireguard tunnel.
#
source ${genode_dir}/repos/dde_linux/run/wg_qemu_tap_preamble.inc
create_boot_directory
import_from_depot [depot_user]/src/[base_src] \
[depot_user]/pkg/[drivers_nic_pkg] \
[depot_user]/src/init \
[depot_user]/src/nic_router
install_config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
</parent-provides>
<start name="timer" caps="100">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
<route>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="drivers" caps="1000" managing_system="yes">
<resource name="RAM" quantum="32M"/>
<binary name="init"/>
<route>
<service name="ROM" label="config">
<parent label="drivers.config"/>
</service>
<service name="Timer"> <child name="timer"/> </service>
<service name="Uplink"> <child name="outer_router"/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="outer_router" caps="200">
<binary name="nic_router"/>
<resource name="RAM" quantum="10M"/>
<provides>
<service name="Nic"/>
<service name="Uplink"/>
</provides>
<config verbose_domain_state="yes" dhcp_discover_timeout_sec="1">
<policy label_prefix="drivers" domain="uplink"/>
<policy label="wireguard -> nic_session" domain="downlink"/>
<domain name="uplink">
<nat domain="downlink" udp-ports="100"/>
</domain>
<domain name="downlink" interface="10.0.3.1/24">
<dhcp-server ip_first="10.0.3.2"
ip_last="10.0.3.2"
dns_config_from="uplink"/>
<udp dst="10.0.2.1/24">
<permit port="49001" domain="uplink"/>
</udp>
</domain>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="inner_router" caps="200">
<binary name="nic_router"/>
<resource name="RAM" quantum="10M"/>
<provides>
<service name="Nic"/>
<service name="Uplink"/>
</provides>
<config verbose_domain_state="yes" dhcp_discover_timeout_sec="1">
<policy label="wireguard -> uplink_session" domain="uplink"/>
<policy label="ping -> " domain="downlink"/>
<domain name="uplink" interface="10.0.9.2/24" use_arp="no" >
<nat domain="downlink" icmp-ids="100"/>
</domain>
<domain name="downlink" interface="10.1.2.1/24">
<dhcp-server ip_first="10.1.2.2" ip_last="10.1.2.2"/>
<icmp dst="10.0.9.1/24" domain="uplink"/>
</domain>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="wireguard" caps="200">
<resource name="RAM" quantum="10M"/>
<config private_key="8GRSQZMgG1uuvz4APIBqrDmiLj8L886r++hzixjjHFc="
listen_port="49002">
<peer public_key="r1Gslnm82X8NaijsWzPoSFzDZGl2tTJoPa+EJL4gYQw="
endpoint_ip="10.0.2.1"
endpoint_port="49001"
allowed_ip="10.0.9.1/32" />
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="Nic"> <child name="outer_router"/> </service>
<service name="Uplink"> <child name="inner_router"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
<start name="ping" caps="100">
<resource name="RAM" quantum="8M"/>
<config dst_ip="10.0.9.1" period_sec="1" count="3"/>
<route>
<service name="Nic"> <child name="inner_router"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
</route>
</start>
</config> }
build { app/wireguard app/ping }
build_boot_image { wireguard ping }
append wait_for_string "64 bytes from 10.0.9.1.*"
append wait_for_string "64 bytes from 10.0.9.1.*"
append wait_for_string "64 bytes from 10.0.9.1.*\n"
run_genode_until $wait_for_string 60

View File

@ -0,0 +1,110 @@
#
# Preamble for WireGuard tests that run in Qemu and use a Qemu netdev TAP
# device to create a tunnel between the WireGuard device in the guest system
# and a Wireguard device in the host system. This script checks that the
# target platform is supported, installs the correct Qemu arguments, sets up
# the host WireGuard device, and ensures that the host WireGuard setup is
# undone whenever the test terminates.
#
if {[expr ![have_spec arm_64] && ![have_spec x86_64]]} {
puts "Run script is not supported on this platform."
exit 0
}
if {[expr [have_spec arm_64] && ![have_board virt_qemu]]} {
puts "Run script is not supported on this platform."
exit 0
}
if {[expr ![have_include power_on/qemu]]} {
puts "Test requires Qemu."
exit 0
}
append wg_board_qemu_args " -m 512 "
append wg_board_qemu_args " -nographic "
append wg_board_qemu_args " -netdev tap,id=net0,ifname=tap0,script=no,downscript=no "
append wg_board_qemu_args " -smp 4 "
if {[have_board virt_qemu]} {
append wg_board_qemu_args " -global virtio-mmio.force-legacy=false "
append wg_board_qemu_args " -device virtio-net-device,bus=virtio-mmio-bus.0,netdev=net0 "
append wg_board_qemu_args " -M virt,virtualization=true,gic-version=3 "
append wg_board_qemu_args " -cpu cortex-a53 "
} elseif {[have_spec x86_64]} {
append wg_board_qemu_args " -machine q35 "
append wg_board_qemu_args " -net nic,model=e1000,netdev=net0 "
} else {
puts "Run script is not supported on this platform."
exit 0
}
proc board_qemu_args { } {
global wg_board_qemu_args
return $wg_board_qemu_args
}
proc set_up_host_wg {} {
puts "Set up host WireGuard"
exec sudo rm -f udhcpd.conf udhcpd.leases
exec sudo ip tuntap del dev tap0 mode tap
set fd [open udhcpd.conf w]
puts $fd "interface tap0"
puts $fd "start 10.0.2.3"
puts $fd "end 10.0.2.4"
puts $fd "max_leases 2"
puts $fd "lease_file udhcpd.leases"
puts $fd "pidfile udhcpd.pid"
puts $fd "option dns 10.0.2.1 10.0.2.2"
puts $fd "option subnet 255.255.255.0"
puts $fd "option router 10.0.2.1"
close $fd
set fd [open udhcpd.leases w]
close $fd
exec sudo ip tuntap add dev tap0 mode tap user $::tcl_platform(user)
exec sudo ip address flush dev tap0
exec sudo ip address add 10.0.2.1/24 dev tap0
exec sudo ip link set tap0 up
exec sudo udhcpd udhcpd.conf
exec echo "0CtU34qsl97IGiYKSO4tMaF/SJvy04zzeQkhZEbZSk0=" > wg_private_key
exec chmod 700 wg_private_key
exec sudo ip link add wg0 type wireguard
exec sudo ip addr add 10.0.9.1/24 dev wg0
exec sudo wg set wg0 private-key wg_private_key listen-port 49001
exec sudo ip link set wg0 up
exec sudo wg set wg0 peer "GrvyALPZ3PQ2AWM+ovxJqnxSqKpmTyqUui5jH+C8I0E=" allowed-ips 10.0.9.2/32 endpoint 10.0.2.3:49002
}
proc undo_host_wg_setup {} {
puts "Undo host WireGuard setup"
exec sudo pkill -F udhcpd.pid
exec sudo ip link set wg0 down
exec sudo ip link delete dev wg0
exec sudo ip link set tap0 down
exec sudo ip address flush dev tap0
exec sudo ip link delete tap0
exec sudo rm -rf wg_private_key udhcpd.conf udhcpd.leases udhcpd.pid
}
rename exit run_tool_exit
proc exit {{status 0}} {
undo_host_wg_setup
run_tool_exit $status
}
set_up_host_wg

View File

@ -0,0 +1,8 @@
:Warning:
Although in principal functioning, the WireGuard port has not been exposed to a
sufficient amount of real-world testing, so far. Therefore, we strongly
recommend not to use it in any security-critical scenarios! There is no
guarantee that the port meets any of the security goals pursued by the
WireGuard protocol or other WireGuard implementations!

View File

@ -0,0 +1,99 @@
/*
* \brief Cache for received ARP information
* \author Martin Stein
* \date 2016-08-19
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* local includes */
#include <arp_cache.h>
using namespace Net;
using namespace Genode;
/*********************
** Arp_cache_entry **
*********************/
Arp_cache_entry::Arp_cache_entry(Ipv4_address const &ip,
Mac_address const &mac)
:
_ip(ip), _mac(mac)
{ }
bool Arp_cache_entry::_higher(Ipv4_address const &ip) const
{
return memcmp(ip.addr, _ip.addr, sizeof(_ip.addr)) > 0;
}
Arp_cache_result Arp_cache_entry::find_by_ip(Ipv4_address const &ip) const
{
if (ip == _ip) {
return Const_pointer<Arp_cache_entry> { *this };
}
Arp_cache_entry const *const entry = child(_higher(ip));
if (!entry) {
return Arp_cache_result(Arp_cache_error::NO_MATCH);
}
return entry->find_by_ip(ip);
}
void Arp_cache_entry::print(Output &output) const
{
Genode::print(output, _ip, " > ", _mac);
}
/***************
** Arp_cache **
***************/
void Arp_cache::new_entry(Ipv4_address const &ip, Mac_address const &mac)
{
if (_entries[_curr].constructed()) {
remove(&(*_entries[_curr]));
}
_entries[_curr].construct(ip, mac);
Arp_cache_entry &entry = *_entries[_curr];
insert(&entry);
if (_curr < NR_OF_ENTRIES - 1) {
_curr++;
} else {
_curr = 0;
};
}
Arp_cache_result Arp_cache::find_by_ip(Ipv4_address const &ip) const
{
if (!first()) {
return Arp_cache_error::NO_MATCH;
}
return first()->find_by_ip(ip);
}
void Arp_cache::destroy_entries_with_mac(Mac_address const &mac)
{
for (unsigned curr = 0; curr < NR_OF_ENTRIES; curr++) {
try {
Arp_cache_entry &entry = *_entries[curr];
if (entry.mac() != mac) {
continue;
}
log("destroy ARP entry ", entry);
remove(&entry);
_entries[curr].destruct();
} catch (Arp_cache_entry_slot::Deref_unconstructed_object) { }
}
}

View File

@ -0,0 +1,98 @@
/*
* \brief Cache for received ARP information
* \author Martin Stein
* \date 2016-08-19
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _ARP_CACHE_H_
#define _ARP_CACHE_H_
/* Genode includes */
#include <net/ipv4.h>
#include <net/ethernet.h>
#include <util/avl_tree.h>
#include <util/reconstructible.h>
#include <util/attempt.h>
/* dde_linux wireguard includes */
#include <pointer.h>
namespace Net {
enum class Arp_cache_error { NO_MATCH };
class Domain;
class Arp_cache;
class Arp_cache_entry;
using Arp_cache_entry_slot = Genode::Constructible<Arp_cache_entry>;
using Arp_cache_result = Genode::Attempt<Const_pointer<Arp_cache_entry>, Arp_cache_error>;
}
class Net::Arp_cache_entry : public Genode::Avl_node<Arp_cache_entry>
{
private:
Ipv4_address const _ip;
Mac_address const _mac;
bool _higher(Ipv4_address const &ip) const;
public:
Arp_cache_entry(Ipv4_address const &ip, Mac_address const &mac);
Arp_cache_result find_by_ip(Ipv4_address const &ip) const;
/**************
** Avl_node **
**************/
bool higher(Arp_cache_entry *entry) { return _higher(entry->_ip); }
/***************
** Accessors **
***************/
Mac_address const &mac() const { return _mac; }
Ipv4_address const &ip() const { return _ip; }
/*********
** log **
*********/
void print(Genode::Output &output) const;
};
class Net::Arp_cache : public Genode::Avl_tree<Arp_cache_entry>
{
private:
enum {
ENTRIES_SIZE = 1024 * sizeof(Genode::addr_t),
NR_OF_ENTRIES = ENTRIES_SIZE / sizeof(Arp_cache_entry),
};
Arp_cache_entry_slot _entries[NR_OF_ENTRIES];
unsigned _curr = 0;
public:
void new_entry(Ipv4_address const &ip, Mac_address const &mac);
void destroy_entries_with_mac(Mac_address const &mac);
Arp_cache_result find_by_ip(Ipv4_address const &ip) const;
};
#endif /* _ARP_CACHE_H_ */

View File

@ -0,0 +1,40 @@
/*
* \brief Aspect of waiting for an ARP reply
* \author Martin Stein
* \date 2016-08-19
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* local includes */
#include <arp_waiter.h>
using namespace Net;
using namespace Genode;
Arp_waiter::Arp_waiter(Arp_waiter_list &list,
Ipv4_address const &ip,
Packet_descriptor const &packet)
:
_list(list), _le(this), _ip(ip), _packet(packet)
{
_list.insert(&_le);
}
Arp_waiter::~Arp_waiter()
{
_list.remove(&_le);
}
void Arp_waiter::print(Output &output) const
{
Genode::print(output, "IP ", _ip);
}

View File

@ -0,0 +1,66 @@
/*
* \brief Remember packets that wait for ARP replies at different interfaces
* \author Martin Stein
* \date 2016-08-19
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _ARP_WAITER_H_
#define _ARP_WAITER_H_
/* local includes */
#include <list.h>
/* Genode includes */
#include <net/ipv4.h>
#include <nic_session/nic_session.h>
namespace Net {
using Packet_descriptor = ::Nic::Packet_descriptor;
class Arp_waiter;
using Arp_waiter_list_element = Genode::List_element<Arp_waiter>;
using Arp_waiter_list = Net::List<Arp_waiter_list_element>;
}
class Net::Arp_waiter
{
private:
Arp_waiter_list &_list;
Arp_waiter_list_element _le;
Ipv4_address const _ip;
Packet_descriptor const _packet;
public:
Arp_waiter(Arp_waiter_list &list,
Ipv4_address const &ip,
Packet_descriptor const &packet);
~Arp_waiter();
/*********
** Log **
*********/
void print(Genode::Output &output) const;
/***************
** Accessors **
***************/
Ipv4_address const &ip() const { return _ip; }
Packet_descriptor const &packet() const { return _packet; }
};
#endif /* _ARP_WAITER_H_ */

View File

@ -0,0 +1,59 @@
/***************************************************
** FIXME **
** Slightly adapted copy from wireguard-tools. **
** Replace with contrib or Genode implementation **
***************************************************/
/* base includes */
#include <util/string.h>
/* app/wireguard includes */
#include <base64.h>
using namespace Genode;
int decode_base64(const char src[4])
{
int val = 0;
for (unsigned int i = 0; i < 4; ++i)
val |= (-1
+ ((((('A' - 1) - src[i]) & (src[i] - ('Z' + 1))) >> 8) & (src[i] - 64))
+ ((((('a' - 1) - src[i]) & (src[i] - ('z' + 1))) >> 8) & (src[i] - 70))
+ ((((('0' - 1) - src[i]) & (src[i] - ('9' + 1))) >> 8) & (src[i] + 5))
+ ((((('+' - 1) - src[i]) & (src[i] - ('+' + 1))) >> 8) & 63)
+ ((((('/' - 1) - src[i]) & (src[i] - ('/' + 1))) >> 8) & 64)
) << (18 - 6 * i);
return val;
}
bool key_from_base64(uint8_t key[WG_KEY_LEN], const char *base64)
{
unsigned int i;
volatile uint8_t ret = 0;
int val;
char tmp[4];
if (strlen(base64) != WG_KEY_LEN_BASE64 - 1 || base64[WG_KEY_LEN_BASE64 - 2] != '=')
return false;
for (i = 0; i < WG_KEY_LEN / 3; ++i) {
val = decode_base64(&base64[i * 4]);
ret |= (uint8_t)((uint32_t)val >> 31);
key[i * 3 + 0] = (uint8_t)((val >> 16) & 0xff);
key[i * 3 + 1] = (uint8_t)((val >> 8) & 0xff);
key[i * 3 + 2] = (uint8_t)(val & 0xff);
}
tmp[0] = base64[i * 4 + 0];
tmp[1] = base64[i * 4 + 1];
tmp[2] = base64[i * 4 + 2];
tmp[3] = 'A';
val = decode_base64(tmp);
ret |= (uint8_t)(((uint32_t)val >> 31) | (val & 0xff));
key[i * 3 + 0] = (uint8_t)((val >> 16) & 0xff);
key[i * 3 + 1] = (uint8_t)((val >> 8) & 0xff);
return 1 & ((ret - 1) >> 8);
}

View File

@ -0,0 +1,22 @@
/***************************************************
** FIXME **
** Slightly adapted copy from wireguard-tools. **
** Replace with contrib or Genode implementation **
***************************************************/
#ifndef _BASE64_H_
#define _BASE64_H_
/* base includes */
#include <base/stdint.h>
enum {
WG_KEY_LEN = 32,
WG_KEY_LEN_BASE64 = ((((WG_KEY_LEN) + 2) / 3) * 4 + 1),
};
int decode_base64(const char src[4]);
bool key_from_base64(Genode::uint8_t key[WG_KEY_LEN], const char *base64);
#endif /* _BASE64_H_ */

View File

@ -0,0 +1,161 @@
/*
* \brief A differentially updating model of the component configuration
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2022-01-07
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* dde_linux wireguard includes */
#include <config_model.h>
using namespace Genode;
using namespace Net;
using namespace Wireguard;
/******************
** Config_model **
******************/
Config_model::Config_model(Genode::Allocator &alloc)
:
_alloc { alloc }
{ }
void Config_model::update(genode_wg_config_callbacks &callbacks,
Xml_node node)
{
if (!_config.constructed()) {
_config.construct(
node.attribute_value("private_key", Key_base64 { }),
node.attribute_value("listen_port", (uint16_t)0U),
node.attribute_value("interface", Ipv4_address_prefix { }));
uint8_t private_key[WG_KEY_LEN];
if (!_config->private_key_b64().valid() ||
!key_from_base64(private_key, _config->private_key_b64().string())) {
error("Invalid private key!");
}
callbacks.add_device(_config->listen_port(), private_key);
}
Peer_update_policy policy { _alloc, callbacks, _config->listen_port() };
_peers.update_from_xml(policy, node);
}
/**************************
** Config_model::Config **
**************************/
Config_model::Config::Config(Key_base64 private_key_b64,
uint16_t listen_port,
Ipv4_address_prefix interface)
:
_private_key_b64 { private_key_b64 },
_listen_port { listen_port },
_interface { interface }
{ }
/**************************************
** Config_model::Peer_update_policy **
**************************************/
void Config_model::Peer_update_policy::update_element(Element &,
Xml_node )
{ }
Config_model::
Peer_update_policy::Peer_update_policy(Allocator &alloc,
genode_wg_config_callbacks &callbacks,
uint16_t listen_port)
:
_alloc { alloc },
_callbacks { callbacks },
_listen_port { listen_port }
{ }
void Config_model::Peer_update_policy::destroy_element(Element &peer)
{
_callbacks.remove_peer(
_listen_port, peer._endpoint_ip.addr, peer._endpoint_port);
destroy(_alloc, &peer);
}
Config_model::Peer_update_policy::Element &
Config_model::Peer_update_policy::create_element(Xml_node node)
{
Ipv4_address endpoint_ip { node.attribute_value("endpoint_ip", Ipv4_address { }) };
uint16_t endpoint_port { node.attribute_value("endpoint_port", (uint16_t)0U ) };
Key_base64 public_key_b64 { node.attribute_value("public_key", Key_base64 { }) };
Ipv4_address_prefix allowed_ip { node.attribute_value("allowed_ip", Ipv4_address_prefix { }) };
uint8_t public_key[WG_KEY_LEN];
if (!public_key_b64.valid() ||
!key_from_base64(public_key, public_key_b64.string())) {
error("Invalid public key!");
}
if (!allowed_ip.valid()) {
error("Invalid allowed ip!");
}
_callbacks.add_peer(
_listen_port, endpoint_ip.addr, endpoint_port, public_key,
allowed_ip.address.addr, allowed_ip.prefix);
return *(
new (_alloc)
Element(public_key_b64, endpoint_ip, endpoint_port, allowed_ip));
}
bool
Config_model::
Peer_update_policy::element_matches_xml_node(Element const &peer,
Xml_node node)
{
Ipv4_address endpoint_ip { node.attribute_value("endpoint_ip", Ipv4_address { }) };
uint16_t endpoint_port { node.attribute_value("endpoint_port", (uint16_t)0U ) };
Key_base64 public_key_b64 { node.attribute_value("public_key", Key_base64 { }) };
return
(endpoint_ip == peer._endpoint_ip) &&
(endpoint_port == peer._endpoint_port) &&
(public_key_b64 == peer._public_key_b64);
}
bool Config_model::Peer_update_policy::node_is_element(Xml_node node)
{
return node.has_type("peer");
}
/************************
** Config_model::Peer **
************************/
Config_model::Peer::Peer(Key_base64 public_key_b64,
Ipv4_address endpoint_ip,
uint16_t endpoint_port,
Ipv4_address_prefix allowed_ip)
:
_public_key_b64 { public_key_b64 },
_endpoint_ip { endpoint_ip },
_endpoint_port { endpoint_port },
_allowed_ip { allowed_ip }
{ }

View File

@ -0,0 +1,125 @@
/*
* \brief A differentially updating model of the component configuration
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2022-01-07
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _CONFIG_MODEL_H_
#define _CONFIG_MODEL_H_
/* base includes */
#include <util/list_model.h>
#include <util/reconstructible.h>
#include <base/allocator.h>
/* app/wireguard includes */
#include <genode_c_api/wireguard.h>
#include <base64.h>
#include <ipv4_address_prefix.h>
namespace Wireguard {
class Config_model;
}
class Wireguard::Config_model
{
private:
using Key_base64 = Genode::String<WG_KEY_LEN_BASE64>;
class Peer;
class Peer_update_policy;
class Config
{
private:
Key_base64 const _private_key_b64;
Genode::uint16_t const _listen_port;
Net::Ipv4_address_prefix const _interface;
public:
Config(Key_base64 private_key_b64,
Genode::uint16_t listen_port,
Net::Ipv4_address_prefix interface);
Key_base64 const &private_key_b64() const { return _private_key_b64; }
Genode::uint16_t listen_port() const { return _listen_port; }
Net::Ipv4_address_prefix const &interface() const { return _interface; }
};
Genode::Allocator &_alloc;
Genode::Constructible<Config> _config { };
Genode::List_model<Peer> _peers { };
public:
Config_model(Genode::Allocator &alloc);
void update(genode_wg_config_callbacks &callbacks,
Genode::Xml_node config_node);
};
class Wireguard::Config_model::Peer : public Genode::List_model<Peer>::Element
{
friend class Peer_update_policy;
private:
Key_base64 _public_key_b64;
Net::Ipv4_address _endpoint_ip;
Genode::uint16_t _endpoint_port;
Net::Ipv4_address_prefix _allowed_ip;
public:
Peer(Key_base64 public_key_b64,
Net::Ipv4_address endpoint_ip,
Genode::uint16_t endpoint_port,
Net::Ipv4_address_prefix allowed_ip);
};
class Wireguard::Config_model::Peer_update_policy
:
public Genode::List_model<Peer>::Update_policy
{
private:
Genode::Allocator &_alloc;
genode_wg_config_callbacks &_callbacks;
Genode::uint16_t _listen_port;
public:
Peer_update_policy(Genode::Allocator &alloc,
genode_wg_config_callbacks &callbacks,
Genode::uint16_t listen_port);
void destroy_element(Element &peer);
Element & create_element(Genode::Xml_node node);
void update_element(Element &peer,
Genode::Xml_node node);
static bool element_matches_xml_node(Element const &peer,
Genode::Xml_node node);
static bool node_is_element(Genode::Xml_node node);
};
#endif /* _CONFIG_MODEL_H_ */

View File

@ -0,0 +1,30 @@
/*
* \brief DHCP related local utilities
* \author Martin Stein
* \date 2021-02-10
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DHCP_H_
#define _DHCP_H_
/* os includes */
#include <net/dhcp.h>
namespace Net {
template <typename T>
static Ipv4_address dhcp_ipv4_option(Dhcp_packet &dhcp)
{
try { return dhcp.option<T>().value(); }
catch (Dhcp_packet::Option_not_found) { return Ipv4_address { }; }
}
}
#endif /* _DHCP_H_ */

View File

@ -0,0 +1,285 @@
/*
* \brief DHCP client state model
* \author Martin Stein
* \date 2016-08-24
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* dde_linux wireguard includes */
#include <dhcp_client.h>
#include <nic_connection.h>
enum { PKT_SIZE = 1024 };
using namespace Genode;
using namespace Net;
using namespace Wireguard;
using Message_type = Dhcp_packet::Message_type;
using Dhcp_options = Dhcp_packet::Options_aggregator<Size_guard>;
/***************
** Utilities **
***************/
void append_param_req_list(Dhcp_options &dhcp_opts)
{
dhcp_opts.append_param_req_list([&] (Dhcp_options::Parameter_request_list_data &data) {
data.append_param_req<Dhcp_packet::Message_type_option>();
data.append_param_req<Dhcp_packet::Server_ipv4>();
data.append_param_req<Dhcp_packet::Ip_lease_time>();
data.append_param_req<Dhcp_packet::Dns_server_ipv4>();
data.append_param_req<Dhcp_packet::Domain_name>();
data.append_param_req<Dhcp_packet::Subnet_mask>();
data.append_param_req<Dhcp_packet::Router_ipv4>();
});
}
/*****************
** Dhcp_client **
*****************/
Dhcp_client::Dhcp_client(Timer::Connection &timer,
Nic_connection &nic_connection)
:
_nic_connection { nic_connection },
_timeout { timer, *this, &Dhcp_client::_handle_timeout }
{ }
void Dhcp_client::discover()
{
_set_state(State::SELECT, _nic_connection.dhcp_discover_timeout());
_send(Message_type::DISCOVER, Ipv4_address(), Ipv4_address(),
Ipv4_address());
}
void Dhcp_client::_rerequest(State next_state)
{
_set_state(next_state, _rerequest_timeout(2));
Ipv4_address const client_ip {
_nic_connection.ip_config().interface().address };
_send(Message_type::REQUEST, client_ip, Ipv4_address(), client_ip);
}
void Dhcp_client::_set_state(State state, Microseconds timeout)
{
_state = state;
_timeout.schedule(timeout);
}
Microseconds Dhcp_client::_rerequest_timeout(unsigned lease_time_div_log2)
{
/* FIXME limit the time because of shortcomings in timeout framework */
enum { MAX_TIMEOUT_SEC = 3600 };
uint64_t timeout_sec = _lease_time_sec >> lease_time_div_log2;
if (timeout_sec > MAX_TIMEOUT_SEC) {
timeout_sec = MAX_TIMEOUT_SEC;
if (_nic_connection.verbose()) {
log("DHCP client: prune re-request timeout");
}
}
return Microseconds(timeout_sec * 1000 * 1000);
}
void Dhcp_client::_handle_timeout(Duration)
{
switch (_state) {
case State::BOUND:
_rerequest(State::RENEW);
break;
case State::RENEW:
_rerequest(State::REBIND);
break;
case State::REBIND:
_nic_connection.discard_ip_config();
discover();
break;
default:
discover();
break;
}
}
void Dhcp_client::handle_eth(Ethernet_frame &eth,
Size_guard &size_guard)
{
if (eth.dst() != _nic_connection.mac_address() &&
eth.dst() != Mac_address(0xff))
{
log("DHCP client: drop packet - ETH.DST does not target me");
return;
}
if (eth.type() != Ethernet_frame::Type::IPV4) {
log("DHCP client: drop packet - ETH.TYPE is not IPV4");
return;
}
Ipv4_packet &ip { eth.data<Ipv4_packet>(size_guard) };
if (ip.protocol() != Ipv4_packet::Protocol::UDP) {
log("DHCP client: drop packet - IPV4.PROTOCOL is not UDP");
return;
}
Udp_packet &udp { ip.data<Udp_packet>(size_guard) };
if (!Dhcp_packet::is_dhcp(&udp)) {
log("DHCP client: drop packet - UDP does not carry DHCP");
return;
}
Dhcp_packet &dhcp = udp.data<Dhcp_packet>(size_guard);
if (dhcp.op() != Dhcp_packet::REPLY) {
log("DHCP client: drop packet - DHCP.OP is not REPLY");
return;
}
if (dhcp.client_mac() != _nic_connection.mac_address()) {
log("DHCP client: drop packet - DHCP.CLIENT_MAC is not my MAC address");
return;
}
try {
Message_type const msg_type =
dhcp.option<Dhcp_packet::Message_type_option>().value();
switch (_state) {
case State::SELECT:
if (msg_type != Message_type::OFFER) {
log("DHCP client: drop packet - DHCP.MSG_TYPE is not OFFER");
return;
}
_set_state(State::REQUEST, _nic_connection.dhcp_request_timeout());
_send(Message_type::REQUEST, Ipv4_address(),
dhcp.option<Dhcp_packet::Server_ipv4>().value(),
dhcp.yiaddr());
break;
case State::REQUEST:
{
if (msg_type != Message_type::ACK) {
log("DHCP client: drop packet - DHCP.MSG_TYPE is not ACK (state REQUEST)");
return;
}
_lease_time_sec = dhcp.option<Dhcp_packet::Ip_lease_time>().value();
_set_state(State::BOUND, _rerequest_timeout(1));
_nic_connection.ip_config_from_dhcp_ack(dhcp);
break;
}
case State::RENEW:
case State::REBIND:
if (msg_type != Message_type::ACK) {
log("DHCP client: drop packet - DHCP.MSG_TYPE is not ACK (state RENEW/REBIND)");
return;
}
_set_state(State::BOUND, _rerequest_timeout(1));
_lease_time_sec = dhcp.option<Dhcp_packet::Ip_lease_time>().value();
break;
default:
log("DHCP client: drop packet - client doesn't expect reply");
return;
}
}
catch (Dhcp_packet::Option_not_found) {
log("DHCP client: drop packet - DHCP.MSG_TYPE missing");
return;
}
}
void Dhcp_client::_send(Message_type msg_type,
Ipv4_address client_ip,
Ipv4_address server_ip,
Ipv4_address requested_ip)
{
Mac_address client_mac = _nic_connection.mac_address();
_nic_connection.send(PKT_SIZE, [&] (void *pkt_base, Size_guard &size_guard) {
/* create ETH header of the request */
Ethernet_frame &eth = Ethernet_frame::construct_at(pkt_base, size_guard);
eth.dst(Mac_address(0xff));
eth.src(client_mac);
eth.type(Ethernet_frame::Type::IPV4);
/* create IP header of the request */
enum { IPV4_TIME_TO_LIVE = 64 };
size_t const ip_off = size_guard.head_size();
Ipv4_packet &ip = eth.construct_at_data<Ipv4_packet>(size_guard);
ip.header_length(sizeof(Ipv4_packet) / 4);
ip.version(4);
ip.time_to_live(IPV4_TIME_TO_LIVE);
ip.protocol(Ipv4_packet::Protocol::UDP);
ip.src(client_ip);
ip.dst(Ipv4_address(0xff));
/* create UDP header of the request */
size_t const udp_off = size_guard.head_size();
Udp_packet &udp = ip.construct_at_data<Udp_packet>(size_guard);
udp.src_port(Port(Dhcp_packet::BOOTPC));
udp.dst_port(Port(Dhcp_packet::BOOTPS));
/* create mandatory DHCP fields of the request */
size_t const dhcp_off = size_guard.head_size();
Dhcp_packet &dhcp = udp.construct_at_data<Dhcp_packet>(size_guard);
dhcp.op(Dhcp_packet::REQUEST);
dhcp.htype(Dhcp_packet::Htype::ETH);
dhcp.hlen(sizeof(Mac_address));
dhcp.ciaddr(client_ip);
dhcp.client_mac(client_mac);
dhcp.default_magic_cookie();
/* append DHCP option fields to the request */
Dhcp_options dhcp_opts(dhcp, size_guard);
dhcp_opts.append_option<Dhcp_packet::Message_type_option>(msg_type);
switch (msg_type) {
case Message_type::DISCOVER:
append_param_req_list(dhcp_opts);
dhcp_opts.append_option<Dhcp_packet::Client_id>(client_mac);
dhcp_opts.append_option<Dhcp_packet::Max_msg_size>((uint16_t)(PKT_SIZE - dhcp_off));
break;
case Message_type::REQUEST:
append_param_req_list(dhcp_opts);
dhcp_opts.append_option<Dhcp_packet::Client_id>(client_mac);
dhcp_opts.append_option<Dhcp_packet::Max_msg_size>((uint16_t)(PKT_SIZE - dhcp_off));
if (_state == State::REQUEST) {
dhcp_opts.append_option<Dhcp_packet::Requested_addr>(requested_ip);
dhcp_opts.append_option<Dhcp_packet::Server_ipv4>(server_ip);
}
break;
default:
class Bad_dhcp_message_type { };
throw Bad_dhcp_message_type { };
}
dhcp_opts.append_option<Dhcp_packet::Options_end>();
/* fill in header values that need the packet to be complete already */
udp.length((uint16_t)(size_guard.head_size() - udp_off));
udp.update_checksum(ip.src(), ip.dst());
ip.total_length(size_guard.head_size() - ip_off);
ip.update_checksum();
});
}

View File

@ -0,0 +1,72 @@
/*
* \brief DHCP client state model
* \author Martin Stein
* \date 2016-08-24
*/
/*
* Copyright (C) 2016-2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DHCP_CLIENT_H_
#define _DHCP_CLIENT_H_
/* base includes */
#include <timer_session/connection.h>
/* dde_linux wireguard includes */
#include <dhcp.h>
namespace Wireguard {
class Nic_connection;
}
namespace Net {
class Ethernet_frame;
class Dhcp_client;
}
class Net::Dhcp_client
{
private:
enum class State
{
INIT = 0, SELECT = 1, REQUEST = 2, BOUND = 3, RENEW = 4, REBIND = 5
};
Wireguard::Nic_connection &_nic_connection;
State _state { State::INIT };
Timer::One_shot_timeout<Dhcp_client> _timeout;
Genode::uint64_t _lease_time_sec = 0;
void _handle_timeout(Genode::Duration);
void _rerequest(State next_state);
Genode::Microseconds _rerequest_timeout(unsigned lease_time_div_log2);
void _set_state(State state, Genode::Microseconds timeout);
void _send(Dhcp_packet::Message_type msg_type,
Ipv4_address client_ip,
Ipv4_address server_ip,
Ipv4_address requested_ip);
public:
Dhcp_client(Timer::Connection &timer,
Wireguard::Nic_connection &nic_connection);
void handle_eth(Ethernet_frame &eth,
Size_guard &size_guard);
void discover();
};
#endif /* _DHCP_CLIENT_H_ */

View File

@ -0,0 +1,269 @@
/**
* \brief Dummy definitions of Linux Kernel functions
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2022-01-07
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <lx_emul.h>
#include <linux/cpuhotplug.h>
int __cpuhp_setup_state(enum cpuhp_state state,const char * name,bool invoke,int (* startup)(unsigned int cpu),int (* teardown)(unsigned int cpu),bool multi_instance)
{
lx_emul_trace(__func__);
return 0;
}
#include <asm/irq_regs.h>
struct pt_regs * __irq_regs = NULL;
#include <asm/preempt.h>
int __preempt_count = 0;
#include <linux/kernel_stat.h>
void account_process_tick(struct task_struct * p,int user_tick)
{
lx_emul_trace(__func__);
}
#include <linux/random.h>
int add_random_ready_callback(struct random_ready_callback * rdy)
{
lx_emul_trace(__func__);
return 0;
}
extern int __init buses_init(void);
int __init buses_init(void)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/sched/loadavg.h>
void calc_global_load(void)
{
lx_emul_trace(__func__);
}
extern int __init classes_init(void);
int __init classes_init(void)
{
lx_emul_trace(__func__);
return 0;
}
extern int __init devices_init(void);
int __init devices_init(void)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/interrupt.h>
int __init early_irq_init(void)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/irq.h>
#include <linux/irqdesc.h>
int generic_handle_irq(unsigned int irq)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/tracepoint-defs.h>
const struct trace_print_flags gfpflag_names[] = { {0,NULL}};
#include <linux/sched/signal.h>
void ignore_signals(struct task_struct * t)
{
lx_emul_trace(__func__);
}
#include <net/ipv6_stubs.h>
const struct ipv6_stub *ipv6_stub = NULL;
#include <linux/prandom.h>
unsigned long net_rand_noise;
#include <linux/tracepoint-defs.h>
const struct trace_print_flags pageflag_names[] = { {0,NULL}};
extern int __init platform_bus_init(void);
int __init platform_bus_init(void)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/rcupdate.h>
void rcu_barrier(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/rcupdate.h>
void rcu_sched_clock_irq(int user)
{
lx_emul_trace(__func__);
}
#include <linux/netdevice.h>
int register_netdevice(struct net_device * dev)
{
lx_emul_trace(__func__);
return 0;
}
#include <net/net_namespace.h>
int register_pernet_device(struct pernet_operations * ops)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/syscore_ops.h>
void register_syscore_ops(struct syscore_ops * ops)
{
lx_emul_trace(__func__);
}
#include <net/sock.h>
void sk_set_memalloc(struct sock * sk)
{
lx_emul_trace(__func__);
}
#include <linux/netdevice.h>
void synchronize_net(void)
{
lx_emul_trace(__func__);
}
#include <linux/timekeeper_internal.h>
void update_vsyscall(struct timekeeper * tk)
{
lx_emul_trace(__func__);
}
#include <linux/tracepoint-defs.h>
const struct trace_print_flags vmaflag_names[] = { {0,NULL}};
#include <linux/rtnetlink.h>
void rtnl_lock(void)
{
lx_emul_trace(__func__);
}
#include <linux/rtnetlink.h>
void rtnl_unlock(void)
{
lx_emul_trace(__func__);
}
#include <linux/netlink.h>
void do_trace_netlink_extack(const char * msg)
{
lx_emul_trace(__func__);
}
#include <linux/netdevice.h>
void napi_enable(struct napi_struct * n)
{
lx_emul_trace(__func__);
}
#include <linux/mmzone.h>
struct mem_section ** mem_section = NULL;
unsigned long phys_base = 0;
#include <asm/atomic.h>
DEFINE_STATIC_KEY_FALSE(bpf_stats_enabled_key);
#include <linux/net.h>
int net_ratelimit(void)
{
lx_emul_trace(__func__);
return 0;
}
__wsum csum_partial(const void * buff,int len,__wsum sum)
{
lx_emul_trace_and_stop(__func__);
}

View File

@ -0,0 +1,468 @@
/*
* \brief Glue code between Genode C++ code and Wireguard C code
* \author Martin Stein
* \date 2022-01-07
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* app/wireguard includes */
#include <genode_c_api/wireguard.h>
#include <lx_emul.h>
/* contrib linux includes */
#include <../drivers/net/wireguard/device.h>
#include <../drivers/net/wireguard/messages.h>
#include <uapi/linux/wireguard.h>
#include <net/genetlink.h>
#include <net/udp_tunnel.h>
/*
* The contrib code expects the private device data to be located directly
+ behind the public data with a certain alignment. It does pointer arithmetic
* based on a pointer to the public data in order to determine the private
* data's base.
*/
struct genode_wg_net_device
{
struct net_device public_data;
struct wg_device private_data __attribute__((aligned(NETDEV_ALIGN)));
int pcpu_refcnt;
}
__attribute__((aligned(NETDEV_ALIGN), packed));
struct genode_wg_nlattr_ifname
{
struct nlattr header;
genode_wg_u8_t data[1] __attribute__((aligned(NLA_ALIGNTO)));
}
__attribute__((aligned(NLA_ALIGNTO), packed));
struct genode_wg_nlattr_private_key
{
struct nlattr header;
genode_wg_u8_t data[NOISE_PUBLIC_KEY_LEN] __attribute__((aligned(NLA_ALIGNTO)));
}
__attribute__((aligned(NLA_ALIGNTO), packed));
struct genode_wg_nlattr_public_key
{
struct nlattr header;
genode_wg_u8_t data[NOISE_PUBLIC_KEY_LEN] __attribute__((aligned(NLA_ALIGNTO)));
}
__attribute__((aligned(NLA_ALIGNTO), packed));
struct genode_wg_nlattr_u8
{
struct nlattr header;
genode_wg_u8_t data __attribute__((aligned(NLA_ALIGNTO)));
}
__attribute__((aligned(NLA_ALIGNTO), packed));
struct genode_wg_nlattr_u16
{
struct nlattr header;
genode_wg_u16_t data __attribute__((aligned(NLA_ALIGNTO)));
}
__attribute__((aligned(NLA_ALIGNTO), packed));
struct genode_wg_nlattr_u32
{
struct nlattr header;
genode_wg_u32_t data __attribute__((aligned(NLA_ALIGNTO)));
}
__attribute__((aligned(NLA_ALIGNTO), packed));
struct genode_wg_nlattr_in_addr
{
struct nlattr header;
struct in_addr data __attribute__((aligned(NLA_ALIGNTO)));
}
__attribute__((aligned(NLA_ALIGNTO), packed));
struct genode_wg_nlattr_sockaddr
{
struct nlattr header;
struct sockaddr data __attribute__((aligned(NLA_ALIGNTO)));
}
__attribute__((aligned(NLA_ALIGNTO), packed));
struct genode_wg_nlattr_allowedip
{
struct nlattr header;
struct genode_wg_nlattr_u16 family __attribute__((aligned(NLA_ALIGNTO)));
struct genode_wg_nlattr_in_addr ipaddr __attribute__((aligned(NLA_ALIGNTO)));
struct genode_wg_nlattr_u8 cidr_mask __attribute__((aligned(NLA_ALIGNTO)));
}
__attribute__((aligned(NLA_ALIGNTO), packed));
struct genode_wg_nlattr_allowedips
{
struct nlattr header;
struct genode_wg_nlattr_allowedip ip_0 __attribute__((aligned(NLA_ALIGNTO)));
}
__attribute__((aligned(NLA_ALIGNTO), packed));
struct genode_wg_nlattr_peer
{
struct nlattr header;
struct genode_wg_nlattr_public_key public_key __attribute__((aligned(NLA_ALIGNTO)));
struct genode_wg_nlattr_sockaddr endpoint __attribute__((aligned(NLA_ALIGNTO)));
struct genode_wg_nlattr_u32 flags __attribute__((aligned(NLA_ALIGNTO)));
struct genode_wg_nlattr_allowedips allowedips __attribute__((aligned(NLA_ALIGNTO)));
}
__attribute__((aligned(NLA_ALIGNTO), packed));
struct genode_wg_nlattr_peers
{
struct nlattr header;
struct genode_wg_nlattr_peer peer_0 __attribute__((aligned(NLA_ALIGNTO)));
}
__attribute__((aligned(NLA_ALIGNTO), packed));
static struct genode_wg_net_device _genode_wg_net_dev;
static struct net _genode_wg_src_net;
static struct nlattr *_genode_wg_tb[1];
static struct nlattr *_genode_wg_data[1];
static struct netlink_ext_ack _genode_wg_extack;
static struct rtnl_link_ops *_genode_wg_rtnl_link_ops;
static struct genl_family *_genode_wg_genl_family;
static struct socket _genode_wg_socket;
/* for the call to wg_set_device that installs listen port and private key */
static struct sock _genode_wg_sock;
static struct sk_buff _genode_wg_sk_buff;
static struct udp_tunnel_sock_cfg _genode_wg_udp_tunnel_cfg;
genode_wg_u16_t _genode_wg_listen_port;
genode_wg_u16_t genode_wg_listen_port(void)
{
return _genode_wg_listen_port;
}
void genode_wg_rtnl_link_ops(struct rtnl_link_ops *ops)
{
_genode_wg_rtnl_link_ops = ops;
}
void genode_wg_genl_family(struct genl_family * family)
{
_genode_wg_genl_family = family;
}
struct net_device * genode_wg_net_device(void)
{
return &_genode_wg_net_dev.public_data;
}
void genode_wg_udp_tunnel_sock_cfg(struct udp_tunnel_sock_cfg * cfg)
{
_genode_wg_udp_tunnel_cfg = *cfg;
}
/**
* Call 'wg_set_device' in the contrib code
*/
static void
_genode_wg_set_device(struct genl_info *info)
{
unsigned idx;
bool op_not_found = true;
for (idx = 0; idx < _genode_wg_genl_family->n_ops; idx++) {
if (_genode_wg_genl_family->ops[idx].cmd == WG_CMD_SET_DEVICE) {
int result = _genode_wg_genl_family->ops[idx].doit(&_genode_wg_sk_buff, info);
if (result != 0) {
printk("Error: op WG_CMD_SET_DEVICE returned %d\n", result);
while (1) { }
}
op_not_found = false;
}
}
if (op_not_found) {
printk("Error: cannot find op WG_CMD_SET_DEVICE\n");
while (1) { }
}
}
void genode_wg_arch_net_dev_init(struct net_device *net_dev,
int *pcpu_refcnt);
static void
_genode_wg_config_add_dev(genode_wg_u16_t listen_port,
const genode_wg_u8_t * const priv_key)
{
static unsigned called = 0;
if (called++) {
printk("%s re-called. Reconfiguration not supported yet\n", __func__);
return;
}
_genode_wg_listen_port = listen_port;
/* prepare environment for the execution of 'wg_set_device' */
_genode_wg_net_dev.public_data.rtnl_link_ops = _genode_wg_rtnl_link_ops;
_genode_wg_net_dev.pcpu_refcnt = 0;
genode_wg_arch_net_dev_init(
&_genode_wg_net_dev.public_data, &_genode_wg_net_dev.pcpu_refcnt);
_genode_wg_sk_buff.sk = &_genode_wg_sock;
_genode_wg_sock.sk_user_data = &_genode_wg_net_dev.private_data;
{
struct genode_wg_nlattr_ifname ifname;
struct genode_wg_nlattr_u16 port;
struct genode_wg_nlattr_private_key private_key;
struct nlattr * attrs[__WGDEVICE_A_LAST];
struct genl_info info;
ifname.data[0] = '\0';
ifname.header.nla_len = sizeof(ifname);
port.data = listen_port;
port.header.nla_len = sizeof(port);
memcpy(private_key.data, priv_key, sizeof(private_key.data));
private_key.header.nla_len = sizeof(private_key);
memset(attrs, 0, sizeof(attrs));
attrs[WGDEVICE_A_IFNAME] = &ifname.header;
attrs[WGDEVICE_A_LISTEN_PORT] = &port.header;
attrs[WGDEVICE_A_PRIVATE_KEY] = &private_key.header;
info.attrs = attrs;
_genode_wg_set_device(&info);
}
/* prepare environment for the execution of 'wg_open' */
_genode_wg_socket.sk = &_genode_wg_sock;
/* trigger execution of 'wg_open' */
_genode_wg_net_dev.public_data.netdev_ops->ndo_open(
&_genode_wg_net_dev.public_data);
}
static void _genode_wg_config_rm_dev(genode_wg_u16_t listen_port)
{
printk("%s not yet implemented\n", __func__);
}
static void
_genode_wg_config_add_peer(genode_wg_u16_t listen_port,
genode_wg_u8_t const endpoint_ip[4],
genode_wg_u16_t endpoint_port,
genode_wg_u8_t const *const pub_key,
genode_wg_u8_t const allowed_ip_addr[4],
genode_wg_u8_t const allowed_ip_prefix_length)
{
struct genode_wg_nlattr_ifname ifname;
struct genode_wg_nlattr_peers peers;
struct nlattr *attrs[__WGDEVICE_A_LAST];
struct genl_info info;
struct genode_wg_nlattr_peer *peer = &peers.peer_0;
struct genode_wg_nlattr_allowedip *allowedip = &peer->allowedips.ip_0;
ifname.data[0] = '\0';
ifname.header.nla_len = sizeof(ifname);
memset(&peers, 0, sizeof(peers));
peers.header.nla_type = WGDEVICE_A_PEERS | NLA_F_NESTED;
peers.header.nla_len = sizeof(peers);
peer->header.nla_len = sizeof(*peer);
peer->header.nla_type |= NLA_F_NESTED;
peer->public_key.header.nla_type = WGPEER_A_PUBLIC_KEY;
peer->public_key.header.nla_len = sizeof(peer->public_key);
memcpy(peer->public_key.data, pub_key, sizeof(peer->public_key.data));
peer->endpoint.header.nla_type = WGPEER_A_ENDPOINT;
peer->endpoint.header.nla_len = sizeof(peer->endpoint);
peer->endpoint.data.sa_family = AF_INET;
peer->endpoint.data.sa_data[0] = ((genode_wg_u8_t*)&endpoint_port)[1];
peer->endpoint.data.sa_data[1] = ((genode_wg_u8_t*)&endpoint_port)[0];
peer->endpoint.data.sa_data[2] = endpoint_ip[0];
peer->endpoint.data.sa_data[3] = endpoint_ip[1];
peer->endpoint.data.sa_data[4] = endpoint_ip[2];
peer->endpoint.data.sa_data[5] = endpoint_ip[3];
peer->flags.header.nla_type = WGPEER_A_FLAGS;
peer->flags.header.nla_len = sizeof(peer->flags);
peer->flags.data = 2; /* I don't know what this value means */
peer->allowedips.header.nla_len = sizeof(peer->allowedips);
peer->allowedips.header.nla_type = WGPEER_A_ALLOWEDIPS | NLA_F_NESTED;
allowedip->header.nla_type |= NLA_F_NESTED;
allowedip->header.nla_len = sizeof(*allowedip);
allowedip->family.header.nla_type = WGALLOWEDIP_A_FAMILY;
allowedip->family.header.nla_len = sizeof(allowedip->family.data) + NLA_HDRLEN;
allowedip->family.data = AF_INET;
allowedip->ipaddr.header.nla_type = WGALLOWEDIP_A_IPADDR;
allowedip->ipaddr.header.nla_len = sizeof(allowedip->ipaddr.data) + NLA_HDRLEN;
memcpy(&allowedip->ipaddr.data, allowed_ip_addr, 4);
allowedip->cidr_mask.header.nla_type = WGALLOWEDIP_A_CIDR_MASK;
allowedip->cidr_mask.header.nla_len = sizeof(allowedip->cidr_mask.data) + NLA_HDRLEN;
allowedip->cidr_mask.data = allowed_ip_prefix_length;
memset(attrs, 0, sizeof(attrs));
attrs[WGDEVICE_A_IFNAME] = &ifname.header;
attrs[WGDEVICE_A_PEERS] = &peers.header;
info.attrs = attrs;
_genode_wg_set_device(&info);
}
static void
_genode_wg_config_rm_peer(genode_wg_u16_t listen_port,
genode_wg_u8_t const endpoint_ip[4],
genode_wg_u16_t endpoint_port)
{
printk("%s not yet implemented\n", __func__);
}
static struct genode_wg_config_callbacks _config_callbacks = {
.add_device = _genode_wg_config_add_dev,
.remove_device = _genode_wg_config_rm_dev,
.add_peer = _genode_wg_config_add_peer,
.remove_peer = _genode_wg_config_rm_peer
};
static void _genode_wg_uplink_connection_receive(void *buf_base,
genode_wg_size_t buf_size)
{
struct iphdr * ip;
size_t data_offset;
struct sk_buff *skb = alloc_skb(buf_size, GFP_KERNEL);
if (!skb) {
printk("Error: alloc_skb failed!\n");
return;
}
skb_reset_network_header(skb);
memcpy(skb_put(skb, buf_size), buf_base, buf_size);
skb->protocol = htons(ETH_P_IP);
skb->dev = genode_wg_net_device();
skb_pull(skb, ETH_HLEN);
skb_reset_network_header(skb);
ip = ip_hdr(skb);
data_offset = ip->ihl * 4;
genode_wg_net_device()->netdev_ops->ndo_start_xmit(skb, genode_wg_net_device());
}
static void _genode_wg_nic_connection_receive(void *buf_base,
genode_wg_size_t buf_size)
{
struct iphdr * ip;
size_t data_offset;
struct sk_buff *skb = alloc_skb(buf_size, GFP_KERNEL);
if (!skb) {
printk("Error: alloc_skb failed!\n");
return;
}
skb_reset_network_header(skb);
memcpy(skb_put(skb, buf_size), buf_base, buf_size);
skb->protocol = htons(ETH_P_IP);
skb->dev = genode_wg_net_device();
skb_pull(skb, ETH_HLEN);
skb_reset_network_header(skb);
ip = ip_hdr(skb);
data_offset = ip->ihl * 4;
skb_pull(skb, data_offset);
skb_reset_transport_header(skb);
_genode_wg_udp_tunnel_cfg.encap_rcv(&_genode_wg_sock, skb);
}
static int user_task_function(void *arg)
{
for (;;) {
genode_wg_update_config(&_config_callbacks);
genode_wg_net_receive(&_genode_wg_uplink_connection_receive,
&_genode_wg_nic_connection_receive);
/* block until lx_emul_task_unblock */
lx_emul_task_schedule(true);
}
return 0;
}
static struct task_struct * _user_task_struct_ptr = NULL;
void lx_user_handle_io(void)
{
if (_user_task_struct_ptr)
lx_emul_task_unblock(_user_task_struct_ptr);
}
void genode_wg_arch_lx_user_init(void);
void lx_user_init(void)
{
pid_t pid;
genode_wg_arch_lx_user_init();
skb_init();
/* trigger execution of 'wg_setup' */
_genode_wg_rtnl_link_ops->setup(&_genode_wg_net_dev.public_data);
/* trigger execution of 'wg_newlink' */
_genode_wg_rtnl_link_ops->newlink(
&_genode_wg_src_net,
&_genode_wg_net_dev.public_data,
_genode_wg_tb,
_genode_wg_data,
&_genode_wg_extack);
/* create user task, which handles network traffic and configuration changes */
pid = kernel_thread(user_task_function, NULL, CLONE_FS | CLONE_FILES);
_user_task_struct_ptr = find_task_by_pid_ns(pid, NULL);
}

View File

@ -0,0 +1,95 @@
/*
* \brief Glue code between Genode C++ code and Wireguard C code
* \author Martin Stein
* \date 2022-01-07
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _GENODE_C_API__WIREGUARD_H_
#define _GENODE_C_API__WIREGUARD_H_
enum { GENODE_WG_KEY_LEN = 32 };
typedef unsigned char genode_wg_u8_t;
typedef unsigned short genode_wg_u16_t;
typedef unsigned int genode_wg_u32_t;
typedef unsigned long genode_wg_size_t;
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*genode_wg_config_add_dev_t)
(genode_wg_u16_t listen_port, const genode_wg_u8_t * const priv_key);
typedef void (*genode_wg_config_rm_dev_t) (genode_wg_u16_t listen_port);
typedef void (*genode_wg_config_add_peer_t) (
genode_wg_u16_t listen_port,
genode_wg_u8_t const endpoint_ip[4],
genode_wg_u16_t endpoint_port,
genode_wg_u8_t const *const pub_key,
genode_wg_u8_t const allowed_ip_addr[4],
genode_wg_u8_t const allowed_ip_prefix
);
typedef void (*genode_wg_config_rm_peer_t)
(genode_wg_u16_t listen_port, genode_wg_u8_t const endpoint_ip[4],
genode_wg_u16_t endpoint_port);
struct genode_wg_config_callbacks
{
genode_wg_config_add_dev_t add_device;
genode_wg_config_rm_dev_t remove_device;
genode_wg_config_add_peer_t add_peer;
genode_wg_config_rm_peer_t remove_peer;
};
void genode_wg_update_config(struct genode_wg_config_callbacks * callbacks);
typedef
void (*genode_wg_uplink_connection_receive_t)(void *buf_base,
genode_wg_size_t buf_size);
typedef void (*genode_wg_nic_connection_receive_t)(void *buf_base,
genode_wg_size_t buf_size);
void
genode_wg_net_receive(genode_wg_uplink_connection_receive_t uplink_rx_callback,
genode_wg_nic_connection_receive_t nic_rx_callback);
genode_wg_u16_t genode_wg_listen_port(void);
void genode_wg_send_wg_prot_at_nic_connection(
genode_wg_u8_t const *wg_prot_base,
genode_wg_size_t wg_prot_size,
genode_wg_u16_t udp_src_port_big_endian,
genode_wg_u16_t udp_dst_port_big_endian,
genode_wg_u32_t ipv4_src_addr_big_endian,
genode_wg_u32_t ipv4_dst_addr_big_endian,
genode_wg_u8_t ipv4_dscp_ecn,
genode_wg_u8_t ipv4_ttl);
void genode_wg_send_ip_at_uplink_connection(
genode_wg_u8_t const *ip_base,
genode_wg_size_t ip_size);
#ifdef __cplusplus
}
#endif
#endif /* _GENODE_C_API__WIREGUARD_H_ */

View File

@ -0,0 +1,103 @@
/*
* \brief Ipv4 address combined with a subnet prefix length
* \author Martin Stein
* \date 2017-10-12
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* local includes */
#include <ipv4_address_prefix.h>
using namespace Genode;
using namespace Net;
Ipv4_address Ipv4_address_prefix::subnet_mask() const
{
Ipv4_address result;
if (prefix >= 8) {
result.addr[0] = 0xff;
if (prefix >= 16) {
result.addr[1] = 0xff;
if (prefix >= 24) {
result.addr[2] = 0xff;
result.addr[3] = 0xff << (32 - prefix);
} else {
result.addr[2] = 0xff << (24 - prefix);
}
} else {
result.addr[1] = 0xff << (16 - prefix);
}
} else {
result.addr[0] = 0xff << (8 - prefix);
}
return result;
}
void Ipv4_address_prefix::print(Genode::Output &output) const
{
Genode::print(output, address, "/", prefix);
}
bool Ipv4_address_prefix::prefix_matches(Ipv4_address const &ip) const
{
uint8_t prefix_left = prefix;
uint8_t byte = 0;
for (; prefix_left >= 8; prefix_left -= 8, byte++) {
if (ip.addr[byte] != address.addr[byte]) {
return false; }
}
if (prefix_left == 0) {
return true; }
uint8_t const mask = (uint8_t)(~(0xff >> prefix_left));
return !((ip.addr[byte] ^ address.addr[byte]) & mask);
}
Ipv4_address Ipv4_address_prefix::broadcast_address() const
{
Ipv4_address result = address;
Ipv4_address const mask = subnet_mask();
for (unsigned i = 0; i < 4; i++) {
result.addr[i] |= (uint8_t)(~mask.addr[i]);
}
return result;
}
Ipv4_address_prefix::Ipv4_address_prefix(Ipv4_address address,
Ipv4_address subnet_mask)
:
address(address), prefix(0)
{
Genode::uint8_t rest;
if (subnet_mask.addr[0] != 0xff) {
rest = subnet_mask.addr[0];
prefix = 0;
} else if (subnet_mask.addr[1] != 0xff) {
rest = subnet_mask.addr[1];
prefix = 8;
} else if (subnet_mask.addr[2] != 0xff) {
rest = subnet_mask.addr[2];
prefix = 16;
} else {
rest = subnet_mask.addr[3];
prefix = 24;
}
for (Genode::uint8_t mask = 1 << 7; rest & mask; mask >>= 1)
prefix++;
}

View File

@ -0,0 +1,82 @@
/*
* \brief Ipv4 address combined with a subnet prefix length
* \author Martin Stein
* \date 2017-10-12
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _IPV4_ADDRESS_PREFIX_H_
#define _IPV4_ADDRESS_PREFIX_H_
/* Genode includes */
#include <net/ipv4.h>
namespace Net {
class Ipv4_address_prefix;
static inline Genode::size_t ascii_to(char const *, Net::Ipv4_address_prefix &);
}
struct Net::Ipv4_address_prefix
{
Ipv4_address address { };
Genode::uint8_t prefix;
Ipv4_address_prefix(Ipv4_address address,
Ipv4_address subnet_mask);
Ipv4_address_prefix() : prefix(32) { }
bool valid() const { return address.valid() || prefix == 0; }
void print(Genode::Output &output) const;
bool prefix_matches(Ipv4_address const &ip) const;
Ipv4_address subnet_mask() const;
Ipv4_address broadcast_address() const;
bool operator != (Ipv4_address_prefix const &other) const
{
return prefix != other.prefix ||
address != other.address;
}
};
Genode::size_t Net::ascii_to(char const *s, Ipv4_address_prefix &result)
{
using namespace Genode;
/* read the leading IPv4 address, fail if there's no address */
Net::Ipv4_address_prefix buf;
size_t read_len = ascii_to(s, buf.address);
if (!read_len) {
return 0; }
/* check for the following slash */
s += read_len;
if (*s != '/') {
return 0; }
read_len++;
s++;
/* read the prefix, fail if there's no prefix */
size_t prefix_len = ascii_to_unsigned(s, buf.prefix, 10);
if (!prefix_len) {
return 0; }
/* fill result and return read length */
result = buf;
return read_len + prefix_len;
}
#endif /* _IPV4_ADDRESS_PREFIX_H_ */

View File

@ -0,0 +1,38 @@
/*
* \brief IPv4 peer configuration
* \author Martin Stein
* \date 2016-08-19
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* dde_linux wireguard includes */
#include <ipv4_config.h>
using namespace Genode;
using namespace Net;
using namespace Wireguard;
Ipv4_config::Ipv4_config()
:
_interface { }
{ }
Ipv4_config::Ipv4_config(Xml_node const &config_node)
:
_interface { config_node.attribute_value("interface", Ipv4_address_prefix()) }
{ }
Ipv4_config::Ipv4_config(Dhcp_packet &dhcp_ack)
:
_interface { dhcp_ack.yiaddr(),
dhcp_ipv4_option<Dhcp_packet::Subnet_mask>(dhcp_ack) }
{ }

View File

@ -0,0 +1,59 @@
/*
* \brief IPv4 peer configuration
* \author Martin Stein
* \date 2016-08-19
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _IPV4_CONFIG_H_
#define _IPV4_CONFIG_H_
/* local includes */
#include <ipv4_address_prefix.h>
#include <dhcp.h>
/* Genode includes */
#include <util/xml_node.h>
namespace Wireguard {
class Ipv4_config;
}
class Wireguard::Ipv4_config
{
private:
Net::Ipv4_address_prefix const _interface;
bool const _interface_valid { _interface.valid() };
bool const _valid { _interface_valid };
public:
Ipv4_config(Net::Dhcp_packet &dhcp_ack);
Ipv4_config(Genode::Xml_node const &config_node);
Ipv4_config();
bool operator != (Ipv4_config const &other) const
{
return _interface != other._interface;
}
/***************
** Accessors **
***************/
bool valid() const { return _valid; }
Net::Ipv4_address_prefix const &interface() const { return _interface; }
};
#endif /* _IPV4_CONFIG_H_ */

View File

@ -0,0 +1,18 @@
#include <lx_emul/irq.h>
#include <lx_kit/env.h>
extern "C" void lx_emul_irq_unmask(unsigned int ) { }
extern "C" void lx_emul_irq_mask(unsigned int ) { }
extern "C" void lx_emul_irq_eoi(unsigned int ) { }
extern "C" unsigned int lx_emul_irq_last()
{
return Lx_kit::env().last_irq;
}

View File

@ -0,0 +1,102 @@
/*
* \brief Genode list with additional functions needed by NIC router
* \author Martin Stein
* \date 2016-08-19
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _LIST_H_
#define _LIST_H_
/* Genode includes */
#include <util/list.h>
#include <base/allocator.h>
namespace Net { template <typename> class List; }
template <typename LT>
struct Net::List : Genode::List<LT>
{
using Base = Genode::List<LT>;
template <typename FUNC>
void for_each(FUNC && functor)
{
for (LT *elem = Base::first(); elem; )
{
LT *const next = elem->Base::Element::next();
functor(*elem);
elem = next;
}
}
template <typename FUNC>
void for_each(FUNC && functor) const
{
for (LT const *elem = Base::first(); elem; )
{
LT const *const next = elem->Base::Element::next();
functor(*elem);
elem = next;
}
}
void destroy_each(Genode::Deallocator &dealloc)
{
while (LT *elem = Base::first()) {
Base::remove(elem);
destroy(dealloc, elem);
}
}
bool empty() const
{
return Base::first() == nullptr;
}
void insert_as_tail(LT const &le)
{
LT *elem { Base::first() };
if (elem) {
while (elem->Base::Element::next()) {
elem = elem->Base::Element::next();
}
}
Base::insert(&le, elem);
}
bool equal_to(List<LT> const &list) const
{
LT const *curr_elem_1 { Base::first() };
LT const *curr_elem_2 { list.Base::first() };
while (true) {
if (curr_elem_1 == nullptr) {
return curr_elem_2 == nullptr;
}
if (curr_elem_2 == nullptr) {
return false;
}
LT const *const next_elem_1 {
curr_elem_1->List<LT>::Element::next() };
LT const *const next_elem_2 {
curr_elem_2->List<LT>::Element::next() };
if (!curr_elem_1->equal_to(*curr_elem_2)) {
return false;
}
curr_elem_1 = next_elem_1;
curr_elem_2 = next_elem_2;
}
}
};
#endif /* _LIST_H_ */

View File

@ -0,0 +1,376 @@
/**
* \brief Dummy definitions of lx_emul
* \author Stefan Kalkowski
* \date 2022-01-10
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* app/wireguard includes */
#include <lx_emul.h>
#include <lx_emul/random.h>
#include <linux/random.h>
void get_random_bytes(void * buf,int nbytes)
{
lx_emul_random_bytes(buf, nbytes);
}
#include <linux/random.h>
int wait_for_random_bytes(void)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/random.h>
u32 get_random_u32(void)
{
u8 buf[4];
lx_emul_random_bytes(buf, sizeof(buf));
return *((u32*)&buf);
}
#include <linux/prandom.h>
u32 prandom_u32(void)
{
u8 buf[4];
lx_emul_random_bytes(buf, sizeof(buf));
return *((u32*)&buf);
}
#include <linux/random.h>
int __must_check get_random_bytes_arch(void * buf,int nbytes)
{
lx_emul_random_bytes(buf, nbytes);
return 0;
}
#include <linux/slab.h>
void * kmalloc_order(size_t size,gfp_t flags,unsigned int order)
{
return kmalloc(size, flags);
}
#include <linux/mm.h>
void * kvmalloc_node(size_t size,gfp_t flags,int node)
{
return kmalloc(size, flags);
}
#include <net/rtnetlink.h>
extern void genode_wg_rtnl_link_ops(struct rtnl_link_ops * ops);
int rtnl_link_register(struct rtnl_link_ops * ops)
{
genode_wg_rtnl_link_ops(ops);
return 0;
}
#include <net/genetlink.h>
extern void genode_wg_genl_family(struct genl_family * family);
int genl_register_family(struct genl_family * family)
{
genode_wg_genl_family(family);
return 0;
}
#include <linux/netdevice.h>
extern struct net_device * genode_wg_net_device(void);
struct net_device * dev_get_by_name(struct net * net,const char * name)
{
return genode_wg_net_device();
}
#include <net/udp_tunnel.h>
int udp_sock_create4(struct net * net,struct udp_port_cfg * cfg,struct socket ** sockp)
{
*sockp = (struct socket*) kmalloc(sizeof(struct socket), GFP_KERNEL);
(*sockp)->sk = (struct sock*) kmalloc(sizeof(struct sock), GFP_KERNEL);
return 0;
}
#include <net/udp_tunnel.h>
extern void genode_wg_udp_tunnel_sock_cfg(struct udp_tunnel_sock_cfg * cfg);
void setup_udp_tunnel_sock(struct net * net,struct socket * sock,struct udp_tunnel_sock_cfg * cfg)
{
genode_wg_udp_tunnel_sock_cfg(cfg);
}
#include <linux/ipv6.h>
bool ipv6_mod_enabled(void)
{
return false;
}
#include <net/udp_tunnel.h>
#include <genode_c_api/wireguard.h>
void udp_tunnel_xmit_skb(
struct rtable * rt,struct sock * sk,struct sk_buff * skb,
__be32 src,__be32 dst,__u8 tos,__u8 ttl,__be16 df,
__be16 src_port,__be16 dst_port,bool xnet,bool nocheck)
{
/*
* FIXME
*
* I don't propagate these values because I found that, at the call to
* udp_tunnel_xmit_skb, Linux sets them hard to the values I'm checking
* for in the following. Furthermore, I assume that they should not be
* relevant for the port anyway.
*/
if (xnet != false) {
pr_info("Error: XNET != false is not expected\n");
while (1) { }
}
if (nocheck != false) {
pr_info("Error: NOCHECK != false is not expected\n");
while (1) { }
}
if (df != 0) {
pr_info("Error: DF != 0 is not expected\n");
while (1) { }
}
/*
* FIXME
*
* Manually set TTL. In the Linux reference scenario this argument is
* observed to be 64. Here it is 0. Further Linux contrib code would have
* to be incorporated in order to make Wireguard provide a correct TTL
* argument. However, it is simpler to set it manually.
*/
if (ttl != 0) {
pr_info("Error: TTL != 0 is not expected\n");
while (1) { }
}
ttl = 64;
/*
* FIXME
*
* Manually set UDP destination port. In the Linux reference scenario this
* argument is observed to be the listen port. Here it is som other port.
* Further Linux contrib code would have to be incorporated in order to
* make Wireguard provide a correct argument. However, it is simpler to
* set it manually.
*/
src_port = htons(genode_wg_listen_port());
/*
* This is the SKB that we put into WireGuard earlier in
* _genode_wg_uplink_connection_receive. WireGuard modified it to become
* the SKB that we want to send at the NIC connection. WireGuard
* assumes that we free the SKB after having sent it.
*/
genode_wg_send_wg_prot_at_nic_connection(
skb->data, skb->len, src_port, dst_port, src, dst,
tos, ttl);
kfree_skb(skb);
}
#include <net/sock.h>
DEFINE_STATIC_KEY_FALSE(memalloc_socks_key);
EXPORT_SYMBOL_GPL(memalloc_socks_key);
#include <linux/slab.h>
struct kmem_cache * kmem_cache_create_usercopy(const char * name,
unsigned int size,
unsigned int align,
slab_flags_t flags,
unsigned int useroffset,
unsigned int usersize,
void (* ctor)(void *))
{
return kmem_cache_create(name, size, align, flags, ctor);
}
#include <net/ip_tunnels.h>
/* Returns either the correct skb->protocol value, or 0 if invalid. */
__be16 ip_tunnel_parse_protocol(const struct sk_buff *skb)
{
//FIXME: we just assume IPv4
return htons(ETH_P_IP);
}
#include <linux/random.h>
bool rng_is_initialized(void)
{
return true;
}
#include <linux/inetdevice.h>
__be32 inet_confirm_addr(struct net * net,struct in_device * in_dev,__be32 dst,__be32 local,int scope)
{
lx_emul_trace(__func__);
return local;
}
#include <net/route.h>
struct rtable * ip_route_output_flow(struct net * net,struct flowi4 * flp4,const struct sock * sk)
{
static bool initialized = false;
static struct dst_metrics dst_default_metrics;
static struct rtable rt;
if (!initialized) {
rt.dst.dev = genode_wg_net_device();
dst_init_metrics(&rt.dst, dst_default_metrics.metrics, true);
initialized = true;
}
return &rt;
}
#include <linux/sched.h>
int __cond_resched(void)
{
if (should_resched(0)) {
schedule();
return 1;
}
return 0;
}
#include <linux/rcupdate.h>
void call_rcu(struct rcu_head * head,rcu_callback_t func)
{
func(head);
}
#include <linux/slab.h>
void kfree_sensitive(const void * p)
{
kfree(p);
}
#include <linux/netdevice.h>
gro_result_t napi_gro_receive(struct napi_struct * napi,struct sk_buff * skb)
{
/*
* This is the SKB that we put into WireGuard earlier in
* _genode_wg_nic_connection_receive. WireGuard modified it to become
* the SKB that we want to send at the Uplink connection. WireGuard
* assumes that we free the SKB after having sent it.
*/
genode_wg_send_ip_at_uplink_connection(skb->data, skb->len);
kfree_skb(skb);
/*
* FIXME
*
* The Wireguard contrib code currently ignores this return value.
* Considering the possibility that, one day, it does otherwise, I return
* an invalid value here in the hope that it complains. The reason is that
* I don't understand GRO and its return values fully and don't want to
* dive into it because I hope that it will not become relevant anyway.
*/
return -1;
}
#include <linux/netdevice.h>
void netif_napi_add(struct net_device * dev,struct napi_struct * napi,int (* poll)(struct napi_struct *,int),int weight)
{
napi->dev = dev;
napi->poll = poll;
napi->weight = weight;
}
#include <linux/netdevice.h>
bool napi_schedule_prep(struct napi_struct * n)
{
return true;
}
#include <linux/netdevice.h>
void __napi_schedule(struct napi_struct * n)
{
int weight = n->weight;
if (n->poll(n, n->weight) >= weight) {
printk("Warning: more work to do?\n");
lx_emul_trace_and_stop(__func__);
}
}
#include <linux/netdevice.h>
bool napi_complete_done(struct napi_struct * n,int work_done)
{
lx_emul_trace(__func__);
return true;
}
#include <linux/once.h>
void __do_once_done(bool * done,struct static_key_true * once_key,unsigned long * flags,struct module * mod)
{
*done = true;
}
#include <linux/once.h>
bool __do_once_start(bool * done,unsigned long * flags)
{
return !*done;
}

View File

@ -0,0 +1,23 @@
/**
* \brief Dummy definitions of Linux Kernel functions
* \author Stefan Kalkowski
* \date 2022-01-07
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Needed to trace and stop */
#include <lx_emul/debug.h>
/* fix for missing includes in generated_dummies */
#include <linux/compiler_attributes.h>
#include <linux/sched/debug.h>
#include <net/rtnetlink.h>
struct rtnl_link_ops *wireguard_rtnl_link_ops(void);

View File

@ -0,0 +1,84 @@
/*
* \brief This file shadows repos/dde_linux/src/lib/lx_emul/alloc.cc
* \author Martin Stein
* \author Stefan Kalkowski
* \date 2021-03-22
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/log.h>
#include <cpu/cache.h>
#include <lx_emul/alloc.h>
#include <lx_emul/page_virt.h>
#include <lx_kit/env.h>
extern "C" void * lx_emul_mem_alloc_aligned(unsigned long size, unsigned long align)
{
void * const ptr = Lx_kit::env().memory.alloc(size, align);
return ptr;
};
extern "C" void * lx_emul_mem_alloc_aligned_uncached(unsigned long size,
unsigned long align)
{
void * const ptr = Lx_kit::env().uncached_memory.alloc(size, align);
return ptr;
};
extern "C" unsigned long lx_emul_mem_dma_addr(void * addr)
{
return (unsigned long)addr;
}
extern "C" unsigned long lx_emul_mem_virt_addr(void * dma_addr)
{
return (unsigned long)dma_addr;
}
extern "C" void lx_emul_mem_free(const void * ptr)
{
if (!ptr)
return;
if (Lx_kit::env().memory.free(ptr))
return;
if (Lx_kit::env().uncached_memory.free(ptr))
return;
Genode::error(__func__, " called with invalid ptr ", ptr);
};
extern "C" unsigned long lx_emul_mem_size(const void * ptr)
{
unsigned long ret = 0;
if (!ptr)
return ret;
if ((ret = Lx_kit::env().memory.size(ptr)))
return ret;
if (!(ret = Lx_kit::env().uncached_memory.size(ptr)))
Genode::error(__func__, " called with invalid ptr ", ptr);
return ret;
};
extern "C" void lx_emul_mem_cache_clean_invalidate(const void * addr,
unsigned long size)
{
Genode::cache_clean_invalidate_data((Genode::addr_t)addr, size);
}
extern "C" void lx_emul_mem_cache_invalidate(const void * addr,
unsigned long size)
{
Genode::cache_invalidate_data((Genode::addr_t)addr, size);
}

View File

@ -0,0 +1,27 @@
/**
* \brief Randomness generation of lx_emul
* \author Stefan Kalkowski
* \date 2022-01-12
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_EMUL__RANDOM_H_
#define _LX_EMUL__RANDOM_H_
#ifdef __cplusplus
extern "C" {
#endif
void lx_emul_random_bytes(void * buf, int bytes);
#ifdef __cplusplus
}
#endif
#endif /* _LX_EMUL__RANDOM_H_ */

View File

@ -0,0 +1,37 @@
/*
* \brief Replaces arch/arm64/kernel/cpufeature.c
* \author Martin Stein
* \date 2022-05-09
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <linux/jump_label.h>
#include <linux/types.h>
/*
* Flag to indicate if we have computed the system wide
* capabilities based on the boot time active CPUs. This
* will be used to determine if a new booting CPU should
* go through the verification process to make sure that it
* supports the system capabilities, without using a hotplug
* notifier. This is also used to decide if we could use
* the fast path for checking constant CPU caps.
*/
DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
EXPORT_SYMBOL(arm64_const_caps_ready);
void finalize_system_capabilities(void)
{
static_branch_enable(&arm64_const_caps_ready);
}
DEFINE_STATIC_KEY_ARRAY_FALSE(cpu_hwcap_keys, ARM64_NCAPS);
EXPORT_SYMBOL(cpu_hwcap_keys);
DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
EXPORT_SYMBOL(cpu_hwcaps);

View File

@ -0,0 +1,28 @@
#ifndef _LX_KIT__DEVICE_H_
#define _LX_KIT__DEVICE_H_
#include <base/env.h>
#include <base/heap.h>
namespace Platform { struct Connection; }
namespace Lx_kit { struct Device_list; }
struct Platform::Connection
{
Connection(Genode::Env &) {}
};
struct Lx_kit::Device_list
{
Device_list(Genode::Entrypoint &,
Genode::Heap &,
Platform::Connection &) {}
void update() {}
template <typename FN>
void for_each(FN const &) {}
};
#endif /* _LX_KIT__DEVICE_H_ */

View File

@ -0,0 +1,171 @@
/*
* \brief This file shadows repos/dde_linux/src/lib/lx_kit/memory.cc
* \author Martin Stein
* \author Stefan Kalkowski
* \date 2021-03-25
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/log.h>
/* local includes */
#include <lx_kit/memory.h>
#include <lx_kit/map.h>
#include <lx_kit/byte_range.h>
#include <lx_emul/page_virt.h>
void Lx_kit::Mem_allocator::free_buffer(void * addr)
{
Buffer * buffer = nullptr;
_virt_to_dma.apply(Buffer_info::Query_addr(addr),
[&] (Buffer_info const & info) {
buffer = &info.buffer;
});
if (!buffer) {
warning(__func__, ": no memory buffer for addr: ", addr, " found");
return;
}
void const * virt_addr = (void const *)buffer->virt_addr();
void const * dma_addr = (void const *)buffer->dma_addr();
_virt_to_dma.remove(Buffer_info::Query_addr(virt_addr));
_dma_to_virt.remove(Buffer_info::Query_addr(dma_addr));
destroy(_heap, buffer);
}
Genode::Dataspace_capability Lx_kit::Mem_allocator::attached_dataspace_cap(void * addr)
{
Genode::Dataspace_capability ret { };
_virt_to_dma.apply(Buffer_info::Query_addr(addr),
[&] (Buffer_info const & info) {
ret = info.buffer.cap();
});
return ret;
}
void * Lx_kit::Mem_allocator::alloc(size_t size, size_t align)
{
if (!size)
return nullptr;
return _mem.alloc_aligned(size, (unsigned)log2(align)).convert<void *>(
[&] (void *ptr) {
memset(ptr, 0, size);
return ptr; },
[&] (Range_allocator::Alloc_error) {
/*
* Restrict the minimum buffer size to avoid the creation of
* a separate dataspaces for tiny allocations.
*/
size_t const min_buffer_size = 256*1024;
/*
* Allocate one excess byte that is not officially registered at
* the '_mem' ranges. This way, two virtual consecutive ranges
* (that must be assumed to belong to non-contiguous physical
* ranges) can never be merged when freeing an allocation. Such
* a merge would violate the assumption that a both the virtual
* and physical addresses of a multi-page allocation are always
* contiguous.
*/
Buffer & buffer = alloc_buffer(max(size + 1, min_buffer_size));
_mem.add_range(buffer.virt_addr(), buffer.size() - 1);
lx_emul_forget_pages((void*)buffer.virt_addr(), buffer.size());
lx_emul_virt_to_pages((void*)buffer.virt_addr(), (buffer.size() + 0xfff) >> 12);
/* re-try allocation */
return _mem.alloc_aligned(size, (unsigned)log2(align)).convert<void *>(
[&] (void *ptr) {
memset(ptr, 0, size);
return ptr; },
[&] (Range_allocator::Alloc_error) -> void * {
error("memory allocation failed for ", size, " align ", align);
return nullptr; }
);
}
);
}
Genode::addr_t Lx_kit::Mem_allocator::dma_addr(void * addr)
{
addr_t ret = 0UL;
_virt_to_dma.apply(Buffer_info::Query_addr(addr),
[&] (Buffer_info const & info) {
addr_t const offset = (addr_t)addr - info.buffer.virt_addr();
ret = info.buffer.dma_addr() + offset;
});
return ret;
}
Genode::addr_t Lx_kit::Mem_allocator::virt_addr(void * dma_addr)
{
addr_t ret = 0UL;
_dma_to_virt.apply(Buffer_info::Query_addr(dma_addr),
[&] (Buffer_info const & info) {
addr_t const offset = (addr_t)dma_addr - info.buffer.dma_addr();
ret = info.buffer.virt_addr() + offset;
});
return ret;
}
bool Lx_kit::Mem_allocator::free(const void * ptr)
{
if (!_mem.valid_addr((addr_t)ptr))
return false;
using Size_at_error = Allocator_avl::Size_at_error;
_mem.size_at(ptr).with_result(
[&] (size_t) { _mem.free(const_cast<void*>(ptr)); },
[ ] (Size_at_error) { });
return true;
}
Genode::size_t Lx_kit::Mem_allocator::size(const void * ptr)
{
if (!ptr) return 0;
using Size_at_error = Allocator_avl::Size_at_error;
return _mem.size_at(ptr).convert<size_t>([ ] (size_t s) { return s; },
[ ] (Size_at_error) { return 0U; });
}
Lx_kit::Mem_allocator::Mem_allocator(Genode::Env & env,
Heap & heap,
Platform::Connection & platform,
Cache cache_attr)
: _env(env), _heap(heap), _platform(platform), _cache_attr(cache_attr) {}

View File

@ -0,0 +1,255 @@
/*
* \brief Wireguard component
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2022-01-07
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <nic_connection.h>
#include <uplink_connection.h>
/* base includes */
#include <base/component.h>
#include <base/attached_rom_dataspace.h>
#include <base/session_label.h>
#include <timer_session/connection.h>
/* lx-kit includes */
#include <lx_kit/env.h>
/* lx-emul includes */
#include <lx_emul/init.h>
/* lx-user includes */
#include <lx_user/io.h>
/* app/wireguard includes */
#include <genode_c_api/wireguard.h>
#include <base64.h>
#include <config_model.h>
using namespace Genode;
namespace Wireguard { class Main; }
class Wireguard::Main : private Entrypoint::Io_progress_handler,
private Nic_connection_notifier
{
private:
Env &_env;
Timer::Connection _timer { _env };
Heap _heap { _env.ram(), _env.rm() };
Attached_rom_dataspace _config_rom { _env, "config" };
Signal_handler<Main> _config_handler { _env.ep(), *this, &Main::_handle_config };
Io_signal_handler<Main> _signal_handler { _env.ep(), *this, &Main::_handle_signal };
Config_model _config_model { _heap };
Signal_handler<Main> _nic_ip_config_handler { _env.ep(), *this, &Main::_handle_nic_ip_config };
Nic_connection _nic_connection { _env, _heap, _signal_handler, _config_rom.xml(), _timer, *this };
Constructible<Uplink_connection> _uplink_connection { };
void _handle_signal()
{
lx_user_handle_io();
Lx_kit::env().scheduler.schedule();
}
void _handle_config() { _config_rom.update(); }
void _handle_nic_ip_config();
/*****************************
** Nic_connection_notifier **
*****************************/
void notify_about_ip_config_update() override
{
_nic_ip_config_handler.local_submit();
}
public:
Main(Env &env)
:
_env(env)
{
Lx_kit::initialize(_env);
/*
* We have to call the static constructors because otherwise the
* initcall list of the LX kit won't get populated.
*/
_env.exec_static_constructors();
_config_rom.sigh(_config_handler);
_handle_config();
env.ep().register_io_progress_handler(*this);
/* trigger signal handling once after construction */
Signal_transmitter(_signal_handler).submit();
}
/**
* Entrypoint::Io_progress_handler
*/
void handle_io_progress() override
{
if (_uplink_connection.constructed()) {
_uplink_connection->notify_peer();
}
_nic_connection.notify_peer();
}
void update(genode_wg_config_callbacks & callbacks)
{
_config_model.update(callbacks, _config_rom.xml());
}
void net_receive(genode_wg_uplink_connection_receive_t uplink_rcv_callback,
genode_wg_nic_connection_receive_t nic_rcv_callback)
{
if (_uplink_connection.constructed()) {
_uplink_connection->for_each_rx_packet(uplink_rcv_callback);
}
_nic_connection.for_each_rx_packet(nic_rcv_callback);
}
void send_wg_prot_at_nic_connection(
genode_wg_u8_t const *wg_prot_base,
genode_wg_size_t wg_prot_size,
genode_wg_u16_t udp_src_port_big_endian,
genode_wg_u16_t udp_dst_port_big_endian,
genode_wg_u32_t ipv4_src_addr_big_endian,
genode_wg_u32_t ipv4_dst_addr_big_endian,
genode_wg_u8_t ipv4_dscp_ecn,
genode_wg_u8_t ipv4_ttl);
void send_ip_at_uplink_connection(
genode_wg_u8_t const *ip_base,
genode_wg_size_t ip_size);
};
void Wireguard::Main::_handle_nic_ip_config()
{
if (_nic_connection.ip_config().valid()) {
if (!_uplink_connection.constructed()) {
_uplink_connection.construct(_env, _heap, _signal_handler);
}
} else {
if (_uplink_connection.constructed()) {
_uplink_connection.destruct();
}
}
}
void Wireguard::Main::send_wg_prot_at_nic_connection(
genode_wg_u8_t const *wg_prot_base,
genode_wg_size_t wg_prot_size,
genode_wg_u16_t udp_src_port_big_endian,
genode_wg_u16_t udp_dst_port_big_endian,
genode_wg_u32_t ipv4_src_addr_big_endian,
genode_wg_u32_t ipv4_dst_addr_big_endian,
genode_wg_u8_t ipv4_dscp_ecn,
genode_wg_u8_t ipv4_ttl)
{
_nic_connection.send_wg_prot(
wg_prot_base,
wg_prot_size,
udp_src_port_big_endian,
udp_dst_port_big_endian,
ipv4_src_addr_big_endian,
ipv4_dst_addr_big_endian,
ipv4_dscp_ecn,
ipv4_ttl);
}
void Wireguard::Main::send_ip_at_uplink_connection(
genode_wg_u8_t const *ip_base,
genode_wg_size_t ip_size)
{
if (_uplink_connection.constructed()) {
_uplink_connection->send_ip(ip_base, ip_size);
} else {
log("Main: drop packet - uplink connection down");
}
}
static Wireguard::Main & main_object(Genode::Env & env)
{
static Wireguard::Main main { env };
return main;
}
extern "C" void
genode_wg_update_config(struct genode_wg_config_callbacks * callbacks)
{
main_object(Lx_kit::env().env).update(*callbacks);
};
extern "C" void
genode_wg_net_receive(genode_wg_uplink_connection_receive_t uplink_rcv_callback,
genode_wg_nic_connection_receive_t nic_rcv_callback)
{
main_object(Lx_kit::env().env).net_receive(uplink_rcv_callback,
nic_rcv_callback);
}
void genode_wg_send_wg_prot_at_nic_connection(
genode_wg_u8_t const *wg_prot_base,
genode_wg_size_t wg_prot_size,
genode_wg_u16_t udp_src_port_big_endian,
genode_wg_u16_t udp_dst_port_big_endian,
genode_wg_u32_t ipv4_src_addr_big_endian,
genode_wg_u32_t ipv4_dst_addr_big_endian,
genode_wg_u8_t ipv4_dscp_ecn,
genode_wg_u8_t ipv4_ttl)
{
main_object(Lx_kit::env().env).send_wg_prot_at_nic_connection(
wg_prot_base,
wg_prot_size,
udp_src_port_big_endian,
udp_dst_port_big_endian,
ipv4_src_addr_big_endian,
ipv4_dst_addr_big_endian,
ipv4_dscp_ecn,
ipv4_ttl);
}
void genode_wg_send_ip_at_uplink_connection(
genode_wg_u8_t const *ip_base,
genode_wg_size_t ip_size)
{
main_object(Lx_kit::env().env).send_ip_at_uplink_connection(
ip_base,
ip_size);
}
void Component::construct(Env &env)
{
main_object(env);
/*
* Main needs to be constructed before startin Linux code,
* because of genode_wg_* calls
*/
lx_emul_start_kernel(nullptr);
}

View File

@ -0,0 +1,339 @@
/*
* \brief Network back-end towards public network (encrypted UDP tunnel)
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2022-01-07
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* dde_linux wireguard includes */
#include <nic_connection.h>
/* os includes */
#include <net/udp.h>
using namespace Genode;
using namespace Net;
using namespace Wireguard;
Nic_connection::Handle_pkt_result
Nic_connection::_drop_pkt(char const *packet_type,
char const *reason)
{
if (_verbose_pkt_drop) {
log("Drop ", packet_type, " - ", reason);
}
return Handle_pkt_result::DROP_PACKET;
}
void Nic_connection::_connection_tx_flush_acks()
{
while (_connection.tx()->ack_avail()) {
_connection.tx()->release_packet(
_connection.tx()->get_acked_packet());
}
}
Nic_connection::Send_pkt_result
Nic_connection::_finish_send_eth_ipv4_with_eth_dst_set_via_arp(Packet_descriptor pkt,
Mac_address const &eth_dst)
{
void *pkt_base { _connection.tx()->packet_content(pkt) };
Size_guard size_guard { pkt.size() };
Ethernet_frame &eth { Ethernet_frame::cast_from(pkt_base, size_guard) };
eth.dst(eth_dst);
_connection_tx_flush_acks();
_connection.tx()->submit_packet(pkt);
return Send_pkt_result::SUCCEEDED;
}
Nic_connection::Send_pkt_result
Nic_connection::_send_arp_reply(Ethernet_frame &request_eth,
Arp_packet &request_arp)
{
return send(ARP_PACKET_SIZE, [&] (void *reply_base, Size_guard &reply_guard) {
Ethernet_frame &reply_eth {
Ethernet_frame::construct_at(reply_base, reply_guard) };
reply_eth.dst(request_eth.src());
reply_eth.src(_mac_address);
reply_eth.type(Ethernet_frame::Type::ARP);
Arp_packet &reply_arp {
reply_eth.construct_at_data<Arp_packet>(reply_guard) };
reply_arp.hardware_address_type(Arp_packet::ETHERNET);
reply_arp.protocol_address_type(Arp_packet::IPV4);
reply_arp.hardware_address_size(sizeof(Mac_address));
reply_arp.protocol_address_size(sizeof(Ipv4_address));
reply_arp.opcode(Arp_packet::REPLY);
reply_arp.src_mac(_mac_address);
reply_arp.src_ip(request_arp.dst_ip());
reply_arp.dst_mac(request_arp.src_mac());
reply_arp.dst_ip(request_arp.src_ip());
});
}
Nic_connection::Handle_pkt_result
Nic_connection::_handle_arp_request(Ethernet_frame &eth,
Arp_packet &arp)
{
if (ip_config().interface().address != arp.dst_ip()) {
return _drop_pkt("ARP request", "Doesn't target my IP address");
}
if (_send_arp_reply(eth, arp) != Send_pkt_result::SUCCEEDED) {
return _drop_pkt("ARP request", "Sending reply failed");
}
return Handle_pkt_result::ACK_PACKET;
}
Nic_connection::Handle_pkt_result
Nic_connection::_handle_arp(Ethernet_frame &eth,
Size_guard &size_guard)
{
Arp_packet &arp { eth.data<Arp_packet>(size_guard) };
if (!arp.ethernet_ipv4()) {
return _drop_pkt("ARP packet", "Targets unknown protocol");
}
switch (arp.opcode()) {
case Arp_packet::REQUEST: return _handle_arp_request(eth, arp);
case Arp_packet::REPLY: return _handle_arp_reply(arp);
default: return _drop_pkt("ARP packet", "Unexpected opcode");
}
}
void Nic_connection::_broadcast_arp_request(Ipv4_address const &src_ip,
Ipv4_address const &dst_ip)
{
send(ARP_PACKET_SIZE, [&] (void *pkt_base, Size_guard &size_guard) {
/* write Ethernet header */
Ethernet_frame &eth = Ethernet_frame::construct_at(pkt_base, size_guard);
eth.dst(Mac_address(0xff));
eth.src(_mac_address);
eth.type(Ethernet_frame::Type::ARP);
/* write ARP header */
Arp_packet &arp = eth.construct_at_data<Arp_packet>(size_guard);
arp.hardware_address_type(Arp_packet::ETHERNET);
arp.protocol_address_type(Arp_packet::IPV4);
arp.hardware_address_size(sizeof(Mac_address));
arp.protocol_address_size(sizeof(Ipv4_address));
arp.opcode(Arp_packet::REQUEST);
arp.src_mac(_mac_address);
arp.src_ip(src_ip);
arp.dst_mac(Mac_address(0xff));
arp.dst_ip(dst_ip);
});
}
Nic_connection::Handle_pkt_result
Nic_connection::_handle_arp_reply(Arp_packet &arp)
{
_arp_cache.find_by_ip(arp.src_ip()).with_result(
[&] (Const_pointer<Arp_cache_entry>) { },
[&] (Arp_cache_error) {
/* by now, no matching ARP cache entry exists, so create one */
Ipv4_address const ip = arp.src_ip();
_arp_cache.new_entry(ip, arp.src_mac());
/* finish sending packets that waited for the entry */
for (Arp_waiter_list_element *waiter_le = _arp_waiters.first();
waiter_le; ) {
Arp_waiter &waiter = *waiter_le->object();
waiter_le = waiter_le->next();
if (ip != waiter.ip()) {
continue;
}
_finish_send_eth_ipv4_with_eth_dst_set_via_arp(
waiter.packet(), arp.src_mac());
destroy(_alloc, &waiter);
}
}
);
return Handle_pkt_result::ACK_PACKET;
}
Nic_connection::Nic_connection(Env &env,
Allocator &alloc,
Signal_context_capability pkt_stream_sigh,
Xml_node const &config_node,
Timer::Connection &timer,
Nic_connection_notifier &notifier)
:
_alloc { alloc },
_notifier { notifier },
_dhcp_client { timer, *this },
_ip_config { config_node },
_connection { env, &_packet_alloc, BUF_SIZE, BUF_SIZE,
"nic_session" },
_link_state_handler { env.ep(), *this, &Nic_connection::_handle_link_state }
{
_connection.rx_channel()->sigh_ready_to_ack(pkt_stream_sigh);
_connection.rx_channel()->sigh_packet_avail(pkt_stream_sigh);
_connection.tx_channel()->sigh_ack_avail(pkt_stream_sigh);
_connection.tx_channel()->sigh_ready_to_submit(pkt_stream_sigh);
_connection.link_state_sigh(_link_state_handler);
if (ip_config().valid()) {
_notifier.notify_about_ip_config_update();
} else {
_dhcp_client.discover();
}
}
void Nic_connection::_handle_link_state()
{
discard_ip_config();
_dhcp_client.discover();
}
void Nic_connection::for_each_rx_packet(Handle_packet_func handle_packet)
{
typename Nic::Connection::Rx::Sink & rx_sink = *_connection.rx();
for (;;) {
if (!rx_sink.packet_avail() || !rx_sink.ack_slots_free())
break;
Packet_descriptor const packet = rx_sink.peek_packet();
bool const packet_valid = rx_sink.packet_valid(packet)
&& (packet.offset() >= 0);
if (packet_valid) {
void *eth_base { rx_sink.packet_content(packet) };
Size_guard size_guard { packet.size() };
Ethernet_frame &eth { Ethernet_frame::cast_from(eth_base, size_guard) };
if (!ip_config().valid()) {
_dhcp_client.handle_eth(eth, size_guard);
} else {
switch (eth.type()) {
case Ethernet_frame::Type::ARP:
_handle_arp(eth, size_guard);
break;
case Ethernet_frame::Type::IPV4:
handle_packet(eth_base, packet.size());
_notify_peers = true;
break;
default:
_drop_pkt("packet", "Unknown type in Ethernet header");
break;
}
}
}
(void)rx_sink.try_get_packet();
rx_sink.try_ack_packet(packet);
}
}
void Nic_connection::notify_peer()
{
if (_notify_peers) {
_notify_peers = false;
_connection.rx()->wakeup();
_connection.tx()->wakeup();
}
}
void Nic_connection::discard_ip_config()
{
_ip_config.construct();
_notifier.notify_about_ip_config_update();
}
void Nic_connection::ip_config_from_dhcp_ack(Net::Dhcp_packet &dhcp_ack)
{
_ip_config.construct(dhcp_ack);
_notifier.notify_about_ip_config_update();
}
void
Nic_connection::send_wg_prot(uint8_t const *wg_prot_base,
size_t wg_prot_size,
uint16_t udp_src_port_big_endian,
uint16_t udp_dst_port_big_endian,
uint32_t,
uint32_t ipv4_dst_addr_big_endian,
uint8_t ipv4_dscp_ecn,
uint8_t ipv4_ttl)
{
size_t const pkt_size {
sizeof(Ethernet_frame) + sizeof(Ipv4_packet) + sizeof(Udp_packet) +
wg_prot_size };
Ipv4_address const dst_ip {
Ipv4_address::from_uint32_big_endian(ipv4_dst_addr_big_endian) };
_send_eth_ipv4_with_eth_dst_set_via_arp(
pkt_size, dst_ip, [&] (Ethernet_frame &eth, Size_guard &size_guard)
{
/* create ETH header */
eth.src(_mac_address);
eth.type(Ethernet_frame::Type::IPV4);
/* create IP header of the reply */
size_t const ip_off = size_guard.head_size();
Ipv4_packet &ip = eth.construct_at_data<Ipv4_packet>(size_guard);
ip.header_length(sizeof(Ipv4_packet) / 4);
ip.version(4);
ip.time_to_live(ipv4_ttl);
ip.diff_service_ecn(ipv4_dscp_ecn);
ip.protocol(Ipv4_packet::Protocol::UDP);
ip.src_big_endian(ip_config().interface().address.to_uint32_big_endian());
ip.dst_big_endian(ipv4_dst_addr_big_endian);
/* create UDP header of the reply */
size_t const udp_off = size_guard.head_size();
Udp_packet &udp = ip.construct_at_data<Udp_packet>(size_guard);
udp.src_port_big_endian(udp_src_port_big_endian);
udp.dst_port_big_endian(udp_dst_port_big_endian);
/* add Wireguard protocol data */
udp.memcpy_to_data((void *)wg_prot_base, wg_prot_size, size_guard);
/* fill in header values that need the packet to be complete already */
udp.length((uint16_t)(size_guard.head_size() - udp_off));
udp.update_checksum(ip.src(), ip.dst());
ip.total_length(size_guard.head_size() - ip_off);
ip.update_checksum();
});
}

View File

@ -0,0 +1,224 @@
/*
* \brief Network back-end towards public network (encrypted UDP tunnel)
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2022-01-07
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _NIC_CONNECTION_H_
#define _NIC_CONNECTION_H_
/* base includes */
#include <base/duration.h>
/* os includes */
#include <nic_session/connection.h>
#include <nic/packet_allocator.h>
#include <net/ethernet.h>
#include <net/arp.h>
/* dde_linux wireguard includes */
#include <ipv4_address_prefix.h>
#include <arp_cache.h>
#include <arp_waiter.h>
#include <ipv4_config.h>
#include <dhcp_client.h>
namespace Timer
{
class Connection;
}
namespace Net {
class Dhcp_packet;
}
namespace Wireguard {
class Nic_connection_notifier;
class Nic_connection;
}
class Wireguard::Nic_connection_notifier : Genode::Interface
{
public:
virtual void notify_about_ip_config_update() = 0;
};
class Wireguard::Nic_connection
{
private:
using Handle_packet_func = void (*)(void *buf_base,
Genode::size_t buf_size);
using Packet_source = Nic::Packet_stream_source<::Nic::Session::Policy>;
enum { PACKET_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE };
enum { WG_PROT_PACKET_SIZE = Nic::Packet_allocator::OFFSET_PACKET_SIZE };
enum { BUF_SIZE = Nic::Connection::Session::QUEUE_SIZE * PACKET_SIZE };
enum {
ETHERNIC_CONNECTION_HEADER_SIZE = sizeof(Net::Ethernet_frame),
ETHERNIC_CONNECTION_DATA_SIZE_WITH_ARP =
sizeof(Net::Arp_packet) + ETHERNIC_CONNECTION_HEADER_SIZE < Net::Ethernet_frame::MIN_SIZE ?
Net::Ethernet_frame::MIN_SIZE - ETHERNIC_CONNECTION_HEADER_SIZE :
sizeof(Net::Arp_packet),
ETHERNIC_CONNECTION_CRC_SIZE = sizeof(Genode::uint32_t),
ARP_PACKET_SIZE =
ETHERNIC_CONNECTION_HEADER_SIZE +
ETHERNIC_CONNECTION_DATA_SIZE_WITH_ARP +
ETHERNIC_CONNECTION_CRC_SIZE,
};
enum Handle_pkt_result { DROP_PACKET, ACK_PACKET };
enum Send_pkt_result { SUCCEEDED, FAILED, PACKET_WAITS_FOR_ARP };
Genode::Allocator &_alloc;
Nic_connection_notifier &_notifier;
Net::Dhcp_client _dhcp_client;
Genode::Reconstructible<Ipv4_config> _ip_config;
Nic::Packet_allocator _packet_alloc { &_alloc };
bool _notify_peers { true };
Net::Arp_cache _arp_cache { };
Net::Arp_waiter_list _arp_waiters { };
Nic::Connection _connection;
Net::Mac_address const _mac_address { _connection.mac_address() };
bool const _verbose { true };
bool const _verbose_pkt_drop { true };
Genode::Signal_handler<Nic_connection> _link_state_handler;
Send_pkt_result
_finish_send_eth_ipv4_with_eth_dst_set_via_arp(Nic::Packet_descriptor pkt,
Net::Mac_address const &eth_dst);
void _connection_tx_flush_acks();
template <typename FUNC>
Send_pkt_result
_send_eth_ipv4_with_eth_dst_set_via_arp(Genode::size_t pkt_size,
Net::Ipv4_address const &dst_ip,
FUNC && write_to_pkt)
{
Send_pkt_result result { Send_pkt_result::FAILED };
try {
Nic::Packet_descriptor pkt { _connection.tx()->alloc_packet(pkt_size) };
void *pkt_base { _connection.tx()->packet_content(pkt) };
Net::Size_guard size_guard { pkt_size };
Net::Ethernet_frame &eth { Net::Ethernet_frame::construct_at(pkt_base, size_guard) };
write_to_pkt(eth, size_guard);
_arp_cache.find_by_ip(dst_ip).with_result(
[&] (Net::Const_pointer<Net::Arp_cache_entry> entry_ref) {
result = _finish_send_eth_ipv4_with_eth_dst_set_via_arp(
pkt, entry_ref.deref().mac());
},
[&] (Net::Arp_cache_error) {
_broadcast_arp_request(ip_config().interface().address, dst_ip);
new (_alloc) Net::Arp_waiter { _arp_waiters, dst_ip, pkt };
result = Send_pkt_result::PACKET_WAITS_FOR_ARP;
}
);
}
catch (Packet_source::Packet_alloc_failed) {
if (_verbose) {
Genode::log("Failed sending NIC packet - Failed allocating packet");
}
}
return result;
}
Handle_pkt_result _drop_pkt(char const *packet_type,
char const *reason);
Send_pkt_result _send_arp_reply(Net::Ethernet_frame &request_eth,
Net::Arp_packet &request_arp);
Handle_pkt_result _handle_arp_request(Net::Ethernet_frame &eth,
Net::Arp_packet &arp);
Handle_pkt_result _handle_arp(Net::Ethernet_frame &eth,
Net::Size_guard &size_guard);
void _broadcast_arp_request(Net::Ipv4_address const &src_ip,
Net::Ipv4_address const &dst_ip);
Handle_pkt_result _handle_arp_reply(Net::Arp_packet &arp);
void _handle_link_state();
public:
Nic_connection(Genode::Env &env,
Genode::Allocator &heap,
Genode::Signal_context_capability pkt_stream_sigh,
Genode::Xml_node const &config_node,
Timer::Connection &timer,
Nic_connection_notifier &notifier);
void for_each_rx_packet(Handle_packet_func handle_packet);
void notify_peer();
void send_wg_prot(Genode::uint8_t const *wg_prot_base,
Genode::size_t wg_prot_size,
Genode::uint16_t udp_src_port_big_endian,
Genode::uint16_t udp_dst_port_big_endian,
Genode::uint32_t ipv4_src_addr_big_endian,
Genode::uint32_t ipv4_dst_addr_big_endian,
Genode::uint8_t ipv4_dscp_ecn,
Genode::uint8_t ipv4_ttl);
Genode::Microseconds dhcp_discover_timeout() const { return Genode::Microseconds { 3 * 1000 * 1000 }; }
Genode::Microseconds dhcp_request_timeout() const { return Genode::Microseconds { 10 * 1000 * 1000 }; }
Ipv4_config const &ip_config() const { return *_ip_config; }
bool verbose() const { return _verbose; }
void discard_ip_config();
void ip_config_from_dhcp_ack(Net::Dhcp_packet &dhcp_ack);
Net::Mac_address mac_address() const { return _mac_address; }
template <typename FUNC>
Send_pkt_result send(Genode::size_t pkt_size, FUNC && write_to_pkt)
{
try {
Nic::Packet_descriptor pkt { _connection.tx()->alloc_packet(pkt_size) };
void *pkt_base { _connection.tx()->packet_content(pkt) };
Net::Size_guard size_guard { pkt_size };
write_to_pkt(pkt_base, size_guard);
_connection_tx_flush_acks();
_connection.tx()->submit_packet(pkt);
}
catch (Packet_source::Packet_alloc_failed) {
if (_verbose) {
Genode::log("Failed sending NIC packet - Failed allocating packet");
}
return Send_pkt_result::FAILED;
}
return Send_pkt_result::SUCCEEDED;
}
};
#endif /* _NIC_CONNECTION_H_ */

View File

@ -0,0 +1,48 @@
/*
* \brief Pointer that can be dereferenced only when valid
* \author Martin Stein
* \date 2017-03-08
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _POINTER_H_
#define _POINTER_H_
/* Genode includes */
#include <base/exception.h>
namespace Net { template <typename> class Const_pointer; }
template <typename T>
class Net::Const_pointer
{
private:
T const *_ptr { nullptr };
public:
struct Invalid : Genode::Exception { };
Const_pointer() { }
Const_pointer(T const &ref) : _ptr(&ref) { }
T const &deref() const
{
if (_ptr == nullptr) {
throw Invalid();
}
return *_ptr;
}
bool valid() const { return _ptr != nullptr; }
};
#endif /* _POINTER_H_ */

View File

@ -0,0 +1,36 @@
/*
* \brief Randomness backend for lx_emul
* \author Stefan Kalkowski
* \date 2022-01-12
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/log.h>
#include <lx_kit/env.h>
#include <lx_emul/random.h>
#include <jitterentropy.h>
extern "C" void lx_emul_random_bytes(void * buf, int bytes)
{
static rand_data * jent = nullptr;
if (!jent) {
jitterentropy_init(Lx_kit::env().heap);
if (jent_entropy_init() != 0)
Genode::error("jitterentropy library could not be initialized!");
jent = jent_entropy_collector_alloc(0, 0);
if (!jent)
Genode::error("jitterentropy could not allocate entropy collector!");
}
jent_read_entropy(jent, (char*)buf, bytes);
}

View File

@ -0,0 +1,113 @@
/**
* \brief Architecture-specific dummy definitions of Linux Kernel functions
* \author Martin Stein
* \date 2022-05-09
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <lx_emul.h>
#include <lx_emul/time.h>
unsigned long long sched_clock(void)
{
return lx_emul_time_counter() * 1000;
}
#include <asm/cpufeature.h>
bool cpu_have_feature(unsigned int num)
{
return 0;
}
u64 vabits_actual;
void rcu_read_unlock_strict(void)
{
lx_emul_trace(__func__);
}
unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/of_fdt.h>
void __init unflatten_device_tree(void)
{
lx_emul_trace(__func__);
}
#include <linux/of_fdt.h>
bool __init early_init_dt_scan(void * params)
{
lx_emul_trace(__func__);
return false;
}
void __init irqchip_init(void) {
lx_emul_trace(__func__);
}
#include <linux/sched_clock.h>
void __init sched_clock_register(u64 (* read)(void),int bits,unsigned long rate)
{
lx_emul_trace(__func__);
}
#include <linux/of_clk.h>
void __init of_clk_init(const struct of_device_id * matches)
{
lx_emul_trace(__func__);
}
#include <linux/sched_clock.h>
void __init generic_sched_clock_init(void)
{
lx_emul_trace(__func__);
}
#include <linux/sched.h>
void do_set_cpus_allowed(struct task_struct * p,const struct cpumask * new_mask)
{
lx_emul_trace(__func__);
}
#include <linux/of.h>
void __init of_core_init(void)
{
lx_emul_trace(__func__);
}
#include <linux/stop_machine.h>
int stop_machine(cpu_stop_fn_t fn,void * data,const struct cpumask * cpus)
{
return (*fn)(data);
}
#include <linux/rcutree.h>
void kvfree(const void * addr)
{
lx_emul_trace_and_stop(__func__);
}

View File

@ -0,0 +1,693 @@
/*
* \brief Dummy definitions of Linux Kernel functions
* \author Automatically generated file - do no edit
* \date 2022-05-04
*/
#include <lx_emul.h>
#include <linux/ratelimit_types.h>
int ___ratelimit(struct ratelimit_state * rs,const char * func)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/gfp.h>
struct page * __alloc_pages(gfp_t gfp,unsigned int order,int preferred_nid,nodemask_t * nodemask)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/clk-provider.h>
const char * __clk_get_name(const struct clk * clk)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/gfp.h>
unsigned long __get_free_pages(gfp_t gfp_mask,unsigned int order)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/icmp.h>
void __icmp_send(struct sk_buff * skb_in,int type,int code,__be32 info,const struct ip_options * opt)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/ipv6.h>
int __ipv6_addr_type(const struct in6_addr * addr)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irqdomain.h>
struct irq_domain * __irq_domain_add(struct fwnode_handle * fwnode,int size,irq_hw_number_t hwirq_max,int direct_max,const struct irq_domain_ops * ops,void * host_data)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irqdomain.h>
struct irq_desc * __irq_resolve_mapping(struct irq_domain * domain,irq_hw_number_t hwirq,unsigned int * irq)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
void __netif_napi_del(struct napi_struct * napi)
{
lx_emul_trace_and_stop(__func__);
}
#include <asm-generic/percpu.h>
unsigned long __per_cpu_offset[NR_CPUS] = {};
#include <linux/mm.h>
void __put_page(struct page * page)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched/task.h>
void __put_task_struct(struct task_struct * tsk)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
struct sk_buff * __skb_gso_segment(struct sk_buff * skb,netdev_features_t features,bool tx_path)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/ctype.h>
const unsigned char _ctype[] = {};
#include <linux/mm.h>
atomic_long_t _totalram_pages;
#include <crypto/internal/hash.h>
int crypto_register_shash(struct shash_alg * alg)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
struct net_device * dev_get_by_index(struct net * net,int ifindex)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
void dev_get_tstats64(struct net_device * dev,struct rtnl_link_stats64 * s)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
asmlinkage __visible void dump_stack(void)
{
lx_emul_trace_and_stop(__func__);
}
extern void flush_dcache_page(struct page * page);
void flush_dcache_page(struct page * page)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
void free_netdev(struct net_device * dev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/gfp.h>
void free_pages(unsigned long addr,unsigned int order)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched/user.h>
void free_uid(struct user_struct * up)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
unsigned int fwnode_count_parents(const struct fwnode_handle * fwnode)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
const char * fwnode_get_name(const struct fwnode_handle * fwnode)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
const char * fwnode_get_name_prefix(const struct fwnode_handle * fwnode)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
struct fwnode_handle * fwnode_get_nth_parent(struct fwnode_handle * fwnode,unsigned int depth)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
void fwnode_handle_put(struct fwnode_handle * fwnode)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/genetlink.h>
void * genlmsg_put(struct sk_buff * skb,u32 portid,u32 seq,const struct genl_family * family,int flags,u8 cmd)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/gfp.h>
bool gfp_pfmemalloc_allowed(gfp_t gfp_mask)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/uuid.h>
const u8 guid_index[16] = {};
#include <linux/irq.h>
void handle_fasteoi_irq(struct irq_desc * desc)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/kernel.h>
const char hex_asc[] = {};
#include <linux/kernel.h>
const char hex_asc_upper[] = {};
#include <linux/icmpv6.h>
void icmp6_send(struct sk_buff * skb,u8 type,u8 code,__u32 info,const struct in6_addr * force_saddr,const struct inet6_skb_parm * parm)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/in6.h>
const struct in6_addr in6addr_any;
#include <net/netfilter/nf_conntrack.h>
struct net init_net;
#include <linux/sched.h>
void io_schedule_finish(int token)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched.h>
int io_schedule_prepare(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched.h>
long __sched io_schedule_timeout(long timeout)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/ipv6.h>
int ip6_dst_hoplimit(struct dst_entry * dst)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/ip_tunnels.h>
const struct header_ops ip_tunnel_header_ops;
#include <net/addrconf.h>
int ipv6_chk_addr(struct net * net,const struct in6_addr * addr,const struct net_device * dev,int strict)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/interrupt.h>
int irq_can_set_affinity(unsigned int irq)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irqdomain.h>
void irq_domain_free_irqs_common(struct irq_domain * domain,unsigned int virq,unsigned int nr_irqs)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irqdomain.h>
void irq_domain_set_info(struct irq_domain * domain,unsigned int virq,irq_hw_number_t hwirq,struct irq_chip * chip,void * chip_data,irq_flow_handler_t handler,void * handler_data,const char * handler_name)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irq.h>
void irq_modify_status(unsigned int irq,unsigned long clr,unsigned long set)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/interrupt.h>
int irq_set_affinity(unsigned int irq,const struct cpumask * cpumask)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irqdomain.h>
void irq_set_default_host(struct irq_domain * domain)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irqnr.h>
struct irq_desc * irq_to_desc(unsigned int irq)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irq_work.h>
void irq_work_tick(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/jiffies.h>
unsigned long volatile __cacheline_aligned_in_smp __jiffy_arch_data jiffies;
#include <linux/slab.h>
int kmem_cache_alloc_bulk(struct kmem_cache * s,gfp_t flags,size_t size,void ** p)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/slab.h>
void kmem_cache_destroy(struct kmem_cache * s)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/kstrtox.h>
int kstrtoll(const char * s,unsigned int base,long long * res)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/delay.h>
unsigned long lpj_fine;
#include <linux/preempt.h>
void migrate_disable(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/preempt.h>
void migrate_enable(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
void napi_disable(struct napi_struct * n)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
void netif_carrier_off(struct net_device * dev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/of.h>
struct property * of_find_property(const struct device_node * np,const char * name,int * lenp)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/of.h>
const struct fwnode_operations of_fwnode_ops;
#include <linux/of.h>
const char * of_prop_next_string(struct property * prop,const char * cur)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/of.h>
int of_property_read_string(const struct device_node * np,const char * propname,const char ** out_string)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/osq_lock.h>
bool osq_lock(struct optimistic_spin_queue * lock)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/osq_lock.h>
void osq_unlock(struct optimistic_spin_queue * lock)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/gfp.h>
void page_frag_free(void * addr)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/percpu_counter.h>
void percpu_counter_add_batch(struct percpu_counter * fbc,s64 amount,s32 batch)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
int printk_deferred(const char * fmt,...)
{
lx_emul_trace_and_stop(__func__);
}
#include <asm-generic/qrwlock.h>
void queued_read_lock_slowpath(struct qrwlock * lock)
{
lx_emul_trace_and_stop(__func__);
}
#include <asm-generic/qspinlock.h>
void queued_spin_lock_slowpath(struct qspinlock * lock,u32 val)
{
lx_emul_trace_and_stop(__func__);
}
#include <asm-generic/qrwlock.h>
void queued_write_lock_slowpath(struct qrwlock * lock)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/rtnetlink.h>
void rtnl_link_unregister(struct rtnl_link_ops * ops)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void sk_clear_memalloc(struct sock * sk)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void sk_error_report(struct sock * sk)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void sk_free(struct sock * sk)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
int skb_checksum_help(struct sk_buff * skb)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void skb_set_owner_w(struct sk_buff * skb,struct sock * sk)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void sock_edemux(struct sk_buff * skb)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/jump_label.h>
bool static_key_initialized;
#include <linux/string_helpers.h>
int string_escape_mem(const char * src,size_t isz,char * dst,size_t osz,unsigned int flags,const char * only)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/clockchips.h>
void tick_broadcast(const struct cpumask * mask)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/timerqueue.h>
bool timerqueue_add(struct timerqueue_head * head,struct timerqueue_node * node)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/timerqueue.h>
bool timerqueue_del(struct timerqueue_head * head,struct timerqueue_node * node)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/timerqueue.h>
struct timerqueue_node * timerqueue_iterate_next(struct timerqueue_node * node)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/udp_tunnel.h>
int udp_sock_create6(struct net * net,struct udp_port_cfg * cfg,struct socket ** sockp)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/udp_tunnel.h>
int udp_tunnel6_xmit_skb(struct dst_entry * dst,struct sock * sk,struct sk_buff * skb,struct net_device * dev,struct in6_addr * saddr,struct in6_addr * daddr,__u8 prio,__u8 ttl,__be32 label,__be16 src_port,__be16 dst_port,bool nocheck)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/udp_tunnel.h>
void udp_tunnel_sock_release(struct socket * sock)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/net_namespace.h>
void unregister_pernet_device(struct pernet_operations * ops)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/uuid.h>
const u8 uuid_index[16] = {};
#include <linux/sched/wake_q.h>
void wake_q_add_safe(struct wake_q_head * head,struct task_struct * task)
{
lx_emul_trace_and_stop(__func__);
}

View File

@ -0,0 +1,17 @@
#include <linux/netdevice.h>
void genode_wg_arch_net_dev_init(struct net_device *net_dev,
int *pcpu_refcnt)
{
net_dev->pcpu_refcnt = pcpu_refcnt;
}
void finalize_system_capabilities(void);
void genode_wg_arch_lx_user_init(void)
{
finalize_system_capabilities();
}

View File

@ -0,0 +1,159 @@
/*
* \brief Array defining order of Linux Kernel initcalls
* \author Automatically generated file - do no edit
* \date 2022-05-05
*/
#pragma once
static const char * lx_emul_initcall_order[] = {
"__initcall_asids_initearly",
"__initcall_start",
"__initcall_spawn_ksoftirqdearly",
"__initcall_migration_initearly",
"__initcall_srcu_bootup_announceearly",
"__initcall_rcu_spawn_gp_kthreadearly",
"__initcall_check_cpu_stall_initearly",
"__initcall_rcu_sysrq_initearly",
"__initcall_cpu_stop_initearly",
"__initcall_init_zero_pfnearly",
"__initcall_its_pmsi_initearly",
"__initcall_its_pci_msi_initearly",
"__initcall_dummy_timer_registerearly",
"__initcall_initialize_ptr_randomearly",
"__initcall_init_mmap_min_addr0",
"__initcall_pci_realloc_setup_params0",
"__initcall_net_ns_init0",
"__initcall_inet_frag_wq_init0",
"__initcall_fpsimd_init1",
"__initcall_enable_mrs_emulation1",
"__initcall_init_amu_fie1",
"__initcall_ksysfs_init1",
"__initcall_rcu_set_runtime_mode1",
"__initcall_dma_init_reserved_memory1",
"__initcall_init_jiffies_clocksource1",
"__initcall_init_elf_binfmt1",
"__initcall_prandom_init_early1",
"__initcall_virtio_init1",
"__initcall_free_raw_capacity1",
"__initcall_sock_init1",
"__initcall_net_defaults_init1",
"__initcall_init_default_flow_dissectors1",
"__initcall_netlink_proto_init1",
"__initcall_genl_init1",
"__initcall_debug_monitors_init2",
"__initcall_dma_atomic_pool_init2",
"__initcall_bdi_class_init2",
"__initcall_mm_sysfs_init2",
"__initcall_init_per_zone_wmark_min2",
"__initcall_pcibus_class_init2",
"__initcall_pci_driver_init2",
"__initcall_amba_init2",
"__initcall_tty_class_init2",
"__initcall_vtconsole_class_init2",
"__initcall_devlink_class_init2",
"__initcall_software_node_init2",
"__initcall_kobject_uevent_init2",
"__initcall_reserve_memblock_reserved_regions3",
"__initcall_vdso_init3",
"__initcall_asids_update_limit3",
"__initcall_of_platform_default_populate_init3s",
"__initcall_topology_init4",
"__initcall_uid_cache_init4",
"__initcall_user_namespace_sysctl_init4",
"__initcall_oom_init4",
"__initcall_default_bdi_init4",
"__initcall_percpu_enable_async4",
"__initcall_init_user_reserve4",
"__initcall_init_admin_reserve4",
"__initcall_init_reserve_notifier4",
"__initcall_aes_init4",
"__initcall_prng_mod_init4",
"__initcall_misc_init4",
"__initcall_register_cpu_capacity_sysctl4",
"__initcall_input_init4",
"__initcall_power_supply_class_init4",
"__initcall_net_dev_init4",
"__initcall_neigh_init4",
"__initcall_fib_notifier_init4",
"__initcall_ethnl_init4",
"__initcall_nexthop_init4",
"__initcall_init_32bit_el0_mask4s",
"__initcall_create_debug_debugfs_entry5",
"__initcall_iomem_init_inode5",
"__initcall_clocksource_done_booting5",
"__initcall_init_pipe_fs5",
"__initcall_anon_inode_init5",
"__initcall_init_ramfs_fs5",
"__initcall_chr_dev_init5",
"__initcall_eth_offload_init5",
"__initcall_ipv4_offload_init5",
"__initcall_inet_init5",
"__initcall_ipv6_offload_init5",
"__initcall_pci_apply_final_quirks5s",
"__initcall_populate_rootfsrootfs",
"__initcall_register_arm64_panic_block6",
"__initcall_cpuinfo_regs_init6",
"__initcall_chacha_simd_mod_init6",
"__initcall_neon_poly1305_mod_init6",
"__initcall_timekeeping_init_ops6",
"__initcall_alarmtimer_init6",
"__initcall_sched_clock_syscore_init6",
"__initcall_kswapd_init6",
"__initcall_mm_compute_batch_init6",
"__initcall_workingset_init6",
"__initcall_fcntl_init6",
"__initcall_start_dirtytime_writeback6",
"__initcall_init_devpts_fs6",
"__initcall_crypto_algapi_init6",
"__initcall_jent_mod_init6",
"__initcall_mod_init6",
"__initcall_mod_init6",
"__initcall_mod_init6",
"__initcall_percpu_counter_startup6",
"__initcall_of_fixed_factor_clk_driver_init6",
"__initcall_of_fixed_clk_driver_init6",
"__initcall_gpio_clk_driver_init6",
"__initcall_virtio_pci_driver_init6",
"__initcall_n_null_init6",
"__initcall_pty_init6",
"__initcall_init6",
"__initcall_hwrng_modinit6",
"__initcall_timeriomem_rng_driver_init6",
"__initcall_cavium_rng_pf_driver_init6",
"__initcall_cavium_rng_vf_driver_init6",
"__initcall_topology_sysfs_init6",
"__initcall_cacheinfo_sysfs_init6",
"__initcall_mod_init6",
"__initcall_net_olddevs_init6",
"__initcall_blackhole_netdev_init6",
"__initcall_virtio_net_driver_init6",
"__initcall_net_failover_init6",
"__initcall_sock_diag_init6",
"__initcall_failover_init6",
"__initcall_gre_offload_init6",
"__initcall_tunnel4_init6",
"__initcall_inet_diag_init6",
"__initcall_tcp_diag_init6",
"__initcall_cubictcp_register6",
"__initcall_inet6_init6",
"__initcall_sit_init6",
"__initcall_init_oops_id7",
"__initcall_printk_late_init7",
"__initcall_check_early_ioremap_leak7",
"__initcall_prandom_init_late7",
"__initcall_pci_resource_alignment_sysfs_init7",
"__initcall_pci_sysfs_init7",
"__initcall_amba_deferred_retry7",
"__initcall_sync_state_resume_initcall7",
"__initcall_deferred_probe_initcall7",
"__initcall_tcp_congestion_default7",
"__initcall_udp_tunnel_nic_init_module7",
"__initcall_ip_auto_config7",
"__initcall_clk_disable_unused7s",
"__initcall_of_platform_sync_state_init7s",
"__initcall_con_initcon",
"__initcall_end",
"__initcall_hvc_console_initcon",
"END_OF_INITCALL_ORDER_ARRAY_DUMMY_ENTRY"
};

View File

@ -0,0 +1,71 @@
arch/arm64/crypto/poly1305-glue.c
arch/arm64/crypto/chacha-neon-glue.c
arch/arm64/lib/memcmp.S
arch/arm64/lib/memchr.S
arch/arm64/lib/strcmp.S
arch/arm64/lib/strlen.S
crypto/skcipher.c
crypto/api.c
lib/hweight.c
lib/cpumask.c
crypto/algapi.c
crypto/memneq.c
crypto/scatterwalk.c
drivers/net/wireguard/allowedips.c
drivers/net/wireguard/cookie.c
drivers/net/wireguard/device.c
drivers/net/wireguard/main.c
drivers/net/wireguard/netlink.c
drivers/net/wireguard/noise.c
drivers/net/wireguard/peer.c
drivers/net/wireguard/peerlookup.c
drivers/net/wireguard/queueing.c
drivers/net/wireguard/ratelimiter.c
drivers/net/wireguard/receive.c
drivers/net/wireguard/send.c
drivers/net/wireguard/socket.c
drivers/net/wireguard/timers.c
kernel/kthread.c
kernel/locking/mutex.c
kernel/locking/rwsem.c
kernel/notifier.c
kernel/sched/clock.c
kernel/sched/completion.c
kernel/sched/swait.c
kernel/sched/wait.c
kernel/time/clockevents.c
kernel/time/clocksource.c
kernel/time/hrtimer.c
kernel/time/jiffies.c
kernel/time/ntp.c
kernel/time/tick-broadcast.c
kernel/time/tick-common.c
kernel/time/time.c
kernel/time/timeconv.c
kernel/time/timecounter.c
kernel/time/timekeeping.c
kernel/time/timer.c
kernel/time/timer_list.c
kernel/workqueue.c
lib/bitmap.c
lib/crypto/blake2s-generic.c
lib/crypto/blake2s.c
lib/crypto/chacha.c
lib/crypto/chacha20poly1305.c
lib/crypto/curve25519-generic.c
lib/crypto/curve25519-hacl64.c
lib/crypto/libchacha.c
lib/find_bit.c
lib/idr.c
lib/nlattr.c
lib/radix-tree.c
lib/refcount.c
lib/scatterlist.c
lib/siphash.c
lib/string.c
lib/vsprintf.c
lib/xarray.c
net/core/dst.c
net/core/dst_cache.c
net/core/flow_dissector.c
net/core/skbuff.c

View File

@ -0,0 +1,5 @@
REQUIRES = arm_64
INC_DIR += $(REP_DIR)/src/include/spec/arm_64
include $(PRG_DIR)/../../target.inc

View File

@ -0,0 +1,26 @@
/**
* \brief Architecture-specific dummy definitions of Linux Kernel functions
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2022-05-09
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <lx_emul.h>
#include <linux/clocksource.h>
void clocksource_arch_init(struct clocksource * cs)
{
lx_emul_trace(__func__);
}
struct cpuinfo_x86 boot_cpu_data __read_mostly;

View File

@ -0,0 +1,596 @@
/*
* \brief Dummy definitions of Linux Kernel functions
* \author Automatically generated file - do no edit
* \date 2022-01-25
*/
#include <lx_emul.h>
#include <linux/ratelimit_types.h>
int ___ratelimit(struct ratelimit_state * rs,const char * func)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/gfp.h>
struct page * __alloc_pages(gfp_t gfp,unsigned int order,int preferred_nid,nodemask_t * nodemask)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/clk-provider.h>
const char * __clk_get_name(const struct clk * clk)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/icmp.h>
void __icmp_send(struct sk_buff * skb_in,int type,int code,__be32 info,const struct ip_options * opt)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/ipv6.h>
int __ipv6_addr_type(const struct in6_addr * addr)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irqdomain.h>
struct irq_domain * __irq_domain_add(struct fwnode_handle * fwnode,int size,irq_hw_number_t hwirq_max,int direct_max,const struct irq_domain_ops * ops,void * host_data)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irqdomain.h>
struct irq_desc * __irq_resolve_mapping(struct irq_domain * domain,irq_hw_number_t hwirq,unsigned int * irq)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
void __netif_napi_del(struct napi_struct * napi)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/mm.h>
void __put_page(struct page * page)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched/task.h>
void __put_task_struct(struct task_struct * tsk)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
struct sk_buff * __skb_gso_segment(struct sk_buff * skb,netdev_features_t features,bool tx_path)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/uaccess.h>
unsigned long _copy_to_user(void __user * to,const void * from,unsigned long n)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/ctype.h>
const unsigned char _ctype[] = {};
extern const char * _parse_integer_fixup_radix(const char * s,unsigned int * base);
const char * _parse_integer_fixup_radix(const char * s,unsigned int * base)
{
lx_emul_trace_and_stop(__func__);
}
extern unsigned int _parse_integer_limit(const char * s,unsigned int base,unsigned long long * p,size_t max_chars);
unsigned int _parse_integer_limit(const char * s,unsigned int base,unsigned long long * p,size_t max_chars)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/mm.h>
atomic_long_t _totalram_pages;
extern void ack_bad_irq(unsigned int irq);
void ack_bad_irq(unsigned int irq)
{
lx_emul_trace_and_stop(__func__);
}
extern int cpu_has_xfeatures(u64 xfeatures_needed,const char ** feature_name);
int cpu_has_xfeatures(u64 xfeatures_needed,const char ** feature_name)
{
lx_emul_trace_and_stop(__func__);
}
#include <crypto/internal/skcipher.h>
int crypto_register_skciphers(struct skcipher_alg * algs,int count)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
struct net_device * dev_get_by_index(struct net * net,int ifindex)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
void dev_get_tstats64(struct net_device * dev,struct rtnl_link_stats64 * s)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
asmlinkage __visible void dump_stack(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
void free_netdev(struct net_device * dev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched/user.h>
void free_uid(struct user_struct * up)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
unsigned int fwnode_count_parents(const struct fwnode_handle * fwnode)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
const char * fwnode_get_name(const struct fwnode_handle * fwnode)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
const char * fwnode_get_name_prefix(const struct fwnode_handle * fwnode)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
struct fwnode_handle * fwnode_get_nth_parent(struct fwnode_handle * fwnode,unsigned int depth)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
void fwnode_handle_put(struct fwnode_handle * fwnode)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/genetlink.h>
void * genlmsg_put(struct sk_buff * skb,u32 portid,u32 seq,const struct genl_family * family,int flags,u8 cmd)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/gfp.h>
bool gfp_pfmemalloc_allowed(gfp_t gfp_mask)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/uuid.h>
const u8 guid_index[16] = {};
#include <linux/kernel.h>
const char hex_asc[] = {};
#include <linux/kernel.h>
const char hex_asc_upper[] = {};
#include <linux/icmpv6.h>
void icmp6_send(struct sk_buff * skb,u8 type,u8 code,__u32 info,const struct in6_addr * force_saddr,const struct inet6_skb_parm * parm)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/in6.h>
const struct in6_addr in6addr_any;
#include <net/netfilter/nf_conntrack.h>
struct net init_net;
#include <linux/sched.h>
void io_schedule_finish(int token)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched.h>
int io_schedule_prepare(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched.h>
long __sched io_schedule_timeout(long timeout)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/ipv6.h>
int ip6_dst_hoplimit(struct dst_entry * dst)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/ip_tunnels.h>
const struct header_ops ip_tunnel_header_ops;
#include <net/addrconf.h>
int ipv6_chk_addr(struct net * net,const struct in6_addr * addr,const struct net_device * dev,int strict)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irqdomain.h>
void irq_domain_free_irqs_common(struct irq_domain * domain,unsigned int virq,unsigned int nr_irqs)
{
lx_emul_trace_and_stop(__func__);
}
extern bool irq_fpu_usable(void);
bool irq_fpu_usable(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irqdomain.h>
void irq_set_default_host(struct irq_domain * domain)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irq_work.h>
void irq_work_tick(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/jiffies.h>
unsigned long volatile __cacheline_aligned_in_smp __jiffy_arch_data jiffies;
extern void kernel_fpu_begin_mask(unsigned int kfpu_mask);
void kernel_fpu_begin_mask(unsigned int kfpu_mask)
{
lx_emul_trace_and_stop(__func__);
}
extern void kernel_fpu_end(void);
void kernel_fpu_end(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/slab.h>
int kmem_cache_alloc_bulk(struct kmem_cache * s,gfp_t flags,size_t size,void ** p)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/slab.h>
void kmem_cache_destroy(struct kmem_cache * s)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/kstrtox.h>
int kstrtoll(const char * s,unsigned int base,long long * res)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/rcutiny.h>
void kvfree(const void * addr)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/delay.h>
unsigned long lpj_fine;
#include <linux/netdevice.h>
void napi_disable(struct napi_struct * n)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
void netif_carrier_off(struct net_device * dev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/gfp.h>
void page_frag_free(void * addr)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
int printk_deferred(const char * fmt,...)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/rtnetlink.h>
void rtnl_link_unregister(struct rtnl_link_ops * ops)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void sk_clear_memalloc(struct sock * sk)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void sk_error_report(struct sock * sk)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void sk_free(struct sock * sk)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
int skb_checksum_help(struct sk_buff * skb)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void skb_set_owner_w(struct sk_buff * skb,struct sock * sk)
{
lx_emul_trace_and_stop(__func__);
}
#include <crypto/internal/skcipher.h>
int skcipher_walk_done(struct skcipher_walk * walk,int err)
{
lx_emul_trace_and_stop(__func__);
}
#include <crypto/internal/skcipher.h>
int skcipher_walk_virt(struct skcipher_walk * walk,struct skcipher_request * req,bool atomic)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void sock_edemux(struct sk_buff * skb)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/jump_label.h>
bool static_key_initialized;
#include <linux/string_helpers.h>
int string_escape_mem(const char * src,size_t isz,char * dst,size_t osz,unsigned int flags,const char * only)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/timerqueue.h>
bool timerqueue_add(struct timerqueue_head * head,struct timerqueue_node * node)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/timerqueue.h>
bool timerqueue_del(struct timerqueue_head * head,struct timerqueue_node * node)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/timerqueue.h>
struct timerqueue_node * timerqueue_iterate_next(struct timerqueue_node * node)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/udp_tunnel.h>
int udp_sock_create6(struct net * net,struct udp_port_cfg * cfg,struct socket ** sockp)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/udp_tunnel.h>
int udp_tunnel6_xmit_skb(struct dst_entry * dst,struct sock * sk,struct sk_buff * skb,struct net_device * dev,struct in6_addr * saddr,struct in6_addr * daddr,__u8 prio,__u8 ttl,__be32 label,__be16 src_port,__be16 dst_port,bool nocheck)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/udp_tunnel.h>
void udp_tunnel_sock_release(struct socket * sock)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/net_namespace.h>
void unregister_pernet_device(struct pernet_operations * ops)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/uuid.h>
const u8 uuid_index[16] = {};
#include <linux/sched/wake_q.h>
void wake_q_add_safe(struct wake_q_head * head,struct task_struct * task)
{
lx_emul_trace_and_stop(__func__);
}

View File

@ -0,0 +1,11 @@
#include <linux/netdevice.h>
void genode_wg_arch_net_dev_init(struct net_device *net_dev,
int *pcpu_refcnt)
{
}
void genode_wg_arch_lx_user_init(void)
{
}

View File

@ -0,0 +1,188 @@
/*
* \brief Array defining order of Linux Kernel initcalls
* \author Automatically generated file - do no edit
* \date 2022-01-06
*/
#pragma once
static const char * lx_emul_initcall_order[] = {
"__initcall_init_hw_perf_eventsearly",
"__initcall_start",
"__initcall_init_real_modeearly",
"__initcall_validate_x2apicearly",
"__initcall_register_nmi_cpu_backtrace_handlerearly",
"__initcall_spawn_ksoftirqdearly",
"__initcall_static_call_initearly",
"__initcall_init_zero_pfnearly",
"__initcall_initialize_ptr_randomearly",
"__initcall_init_mmap_min_addr0",
"__initcall_pci_realloc_setup_params0",
"__initcall_net_ns_init0",
"__initcall_inet_frag_wq_init0",
"__initcall_reboot_init1",
"__initcall_ksysfs_init1",
"__initcall_rcu_set_runtime_mode1",
"__initcall_init_jiffies_clocksource1",
"__initcall_init_elf_binfmt1",
"__initcall_prandom_init_early1",
"__initcall_sock_init1",
"__initcall_net_defaults_init1",
"__initcall_init_default_flow_dissectors1",
"__initcall_netlink_proto_init1",
"__initcall_genl_init1",
"__initcall_bdi_class_init2",
"__initcall_mm_sysfs_init2",
"__initcall_init_per_zone_wmark_min2",
"__initcall_pcibus_class_init2",
"__initcall_pci_driver_init2",
"__initcall_tty_class_init2",
"__initcall_vtconsole_class_init2",
"__initcall_devlink_class_init2",
"__initcall_software_node_init2",
"__initcall_i2c_init2",
"__initcall_amd_postcore_init2",
"__initcall_kobject_uevent_init2",
"__initcall_bts_init3",
"__initcall_pt_init3",
"__initcall_sbf_init3",
"__initcall_arch_kdebugfs_init3",
"__initcall_intel_pconfig_init3",
"__initcall_pci_arch_init3",
"__initcall_init_vdso4",
"__initcall_fixup_ht_bug4",
"__initcall_topology_init4",
"__initcall_uid_cache_init4",
"__initcall_user_namespace_sysctl_init4",
"__initcall_oom_init4",
"__initcall_default_bdi_init4",
"__initcall_percpu_enable_async4",
"__initcall_init_user_reserve4",
"__initcall_init_admin_reserve4",
"__initcall_init_reserve_notifier4",
"__initcall_aes_init4",
"__initcall_prng_mod_init4",
"__initcall_misc_init4",
"__initcall_vga_arb_device_init4",
"__initcall_phy_init4",
"__initcall_serio_init4",
"__initcall_input_init4",
"__initcall_net_dev_init4",
"__initcall_neigh_init4",
"__initcall_fib_notifier_init4",
"__initcall_ethnl_init4",
"__initcall_nexthop_init4",
"__initcall_pci_subsys_init4",
"__initcall_nmi_warning_debugfs5",
"__initcall_hpet_late_init5",
"__initcall_init_amd_nbs5",
"__initcall_iomem_init_inode5",
"__initcall_clocksource_done_booting5",
"__initcall_init_pipe_fs5",
"__initcall_anon_inode_init5",
"__initcall_init_ramfs_fs5",
"__initcall_chr_dev_init5",
"__initcall_eth_offload_init5",
"__initcall_ipv4_offload_init5",
"__initcall_inet_init5",
"__initcall_ipv6_offload_init5",
"__initcall_pcibios_assign_resources5",
"__initcall_pci_apply_final_quirks5s",
"__initcall_populate_rootfsrootfs",
"__initcall_pci_iommu_initrootfs",
"__initcall_rapl_pmu_init6",
"__initcall_amd_uncore_init6",
"__initcall_amd_ibs_init6",
"__initcall_msr_init6",
"__initcall_intel_uncore_init6",
"__initcall_cstate_pmu_init6",
"__initcall_register_kernel_offset_dumper6",
"__initcall_i8259A_init_ops6",
"__initcall_init_tsc_clocksource6",
"__initcall_add_rtc_cmos6",
"__initcall_umwait_init6",
"__initcall_ioapic_init_ops6",
"__initcall_sysfb_init6",
"__initcall_chacha_simd_mod_init6",
"__initcall_blake2s_mod_init6",
"__initcall_poly1305_simd_mod_init6",
"__initcall_curve25519_mod_init6",
"__initcall_timekeeping_init_ops6",
"__initcall_alarmtimer_init6",
"__initcall_perf_event_sysfs_init6",
"__initcall_kswapd_init6",
"__initcall_workingset_init6",
"__initcall_fcntl_init6",
"__initcall_start_dirtytime_writeback6",
"__initcall_init_devpts_fs6",
"__initcall_crypto_algapi_init6",
"__initcall_jent_mod_init6",
"__initcall_mod_init6",
"__initcall_mod_init6",
"__initcall_mod_init6",
"__initcall_gpio_clk_driver_init6",
"__initcall_plt_clk_driver_init6",
"__initcall_n_null_init6",
"__initcall_pty_init6",
"__initcall_serial8250_init6",
"__initcall_serial_pci_driver_init6",
"__initcall_exar_pci_driver_init6",
"__initcall_dw8250_platform_driver_init6",
"__initcall_lpss8250_pci_driver_init6",
"__initcall_mid8250_pci_driver_init6",
"__initcall_hwrng_modinit6",
"__initcall_timeriomem_rng_driver_init6",
"__initcall_mod_init6",
"__initcall_mod_init6",
"__initcall_mod_init6",
"__initcall_topology_sysfs_init6",
"__initcall_cacheinfo_sysfs_init6",
"__initcall_mod_init6",
"__initcall_net_olddevs_init6",
"__initcall_blackhole_netdev_init6",
"__initcall_e100_init_module6",
"__initcall_e1000_init_module6",
"__initcall_e1000_init_module6",
"__initcall_igb_init_module6",
"__initcall_igc_init_module6",
"__initcall_igbvf_init_module6",
"__initcall_ixgbe_init_module6",
"__initcall_i40e_init_module6",
"__initcall_ixgb_init_module6",
"__initcall_i8042_init6",
"__initcall_serport_init6",
"__initcall_atkbd_init6",
"__initcall_psmouse_init6",
"__initcall_hid_init6",
"__initcall_hid_generic_init6",
"__initcall_pmc_atom_init6",
"__initcall_sock_diag_init6",
"__initcall_gre_offload_init6",
"__initcall_tunnel4_init6",
"__initcall_inet_diag_init6",
"__initcall_tcp_diag_init6",
"__initcall_cubictcp_register6",
"__initcall_inet6_init6",
"__initcall_sit_init6",
"__initcall_update_mp_table7",
"__initcall_lapic_insert_resource7",
"__initcall_print_ICs7",
"__initcall_create_tlb_single_page_flush_ceiling7",
"__initcall_init_oops_id7",
"__initcall_sched_clock_init_late7",
"__initcall_printk_late_init7",
"__initcall_check_early_ioremap_leak7",
"__initcall_prandom_init_late7",
"__initcall_pci_resource_alignment_sysfs_init7",
"__initcall_pci_sysfs_init7",
"__initcall_sync_state_resume_initcall7",
"__initcall_deferred_probe_initcall7",
"__initcall_tcp_congestion_default7",
"__initcall_udp_tunnel_nic_init_module7",
"__initcall_ip_auto_config7",
"__initcall_clk_disable_unused7s",
"__initcall_con_initcon",
"__initcall_end",
"__initcall_univ8250_console_initcon",
"END_OF_INITCALL_ORDER_ARRAY_DUMMY_ENTRY"
};

View File

@ -0,0 +1,71 @@
arch/x86/crypto/blake2s-core.S
arch/x86/crypto/blake2s-glue.c
arch/x86/crypto/chacha-avx2-x86_64.S
arch/x86/crypto/chacha-avx512vl-x86_64.S
arch/x86/crypto/chacha-ssse3-x86_64.S
arch/x86/crypto/chacha_glue.c
arch/x86/crypto/curve25519-x86_64.c
arch/x86/crypto/poly1305-x86_64-cryptogams.pl
arch/x86/crypto/poly1305_glue.c
arch/x86/lib/hweight.S
crypto/algapi.c
crypto/memneq.c
crypto/scatterwalk.c
drivers/net/wireguard/allowedips.c
drivers/net/wireguard/cookie.c
drivers/net/wireguard/device.c
drivers/net/wireguard/main.c
drivers/net/wireguard/netlink.c
drivers/net/wireguard/noise.c
drivers/net/wireguard/peer.c
drivers/net/wireguard/peerlookup.c
drivers/net/wireguard/queueing.c
drivers/net/wireguard/ratelimiter.c
drivers/net/wireguard/receive.c
drivers/net/wireguard/send.c
drivers/net/wireguard/socket.c
drivers/net/wireguard/timers.c
kernel/kthread.c
kernel/locking/mutex.c
kernel/locking/rwsem.c
kernel/notifier.c
kernel/sched/clock.c
kernel/sched/completion.c
kernel/sched/swait.c
kernel/sched/wait.c
kernel/time/clockevents.c
kernel/time/clocksource.c
kernel/time/hrtimer.c
kernel/time/jiffies.c
kernel/time/ntp.c
kernel/time/tick-broadcast.c
kernel/time/tick-common.c
kernel/time/time.c
kernel/time/timeconv.c
kernel/time/timecounter.c
kernel/time/timekeeping.c
kernel/time/timer.c
kernel/time/timer_list.c
kernel/workqueue.c
lib/bitmap.c
lib/crypto/blake2s-generic.c
lib/crypto/blake2s.c
lib/crypto/chacha.c
lib/crypto/chacha20poly1305.c
lib/crypto/curve25519-generic.c
lib/crypto/curve25519-hacl64.c
lib/crypto/libchacha.c
lib/find_bit.c
lib/idr.c
lib/nlattr.c
lib/radix-tree.c
lib/refcount.c
lib/scatterlist.c
lib/siphash.c
lib/string.c
lib/vsprintf.c
lib/xarray.c
net/core/dst.c
net/core/dst_cache.c
net/core/flow_dissector.c
net/core/skbuff.c

View File

@ -0,0 +1,5 @@
REQUIRES = x86_64
INC_DIR += $(REP_DIR)/src/include/spec/x86_64
include $(PRG_DIR)/../../target.inc

View File

@ -0,0 +1,21 @@
TARGET = wireguard
LIBS += base net jitterentropy wireguard
GEN_DIR := $(PRG_DIR)/../..
INC_DIR += $(GEN_DIR)
INC_DIR += $(REP_DIR)/src/include
SRC_CC += arp_cache.cc
SRC_CC += arp_waiter.cc
SRC_CC += base64.cc
SRC_CC += config_model.cc
SRC_CC += dhcp_client.cc
SRC_CC += ipv4_address_prefix.cc
SRC_CC += ipv4_config.cc
SRC_CC += irq.cc
SRC_CC += main.cc
SRC_CC += nic_connection.cc
SRC_CC += random.cc
SRC_CC += uplink_connection.cc
vpath %.cc $(GEN_DIR)
CC_CXX_WARN_STRICT_CONVERSION =

View File

@ -0,0 +1,112 @@
/*
* \brief Network back-end towards private network (unencrypted user packets)
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2022-01-07
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* dde_linux wireguard includes */
#include <uplink_connection.h>
/* os includes */
#include <net/ipv4.h>
using namespace Genode;
using namespace Net;
using namespace Wireguard;
void Uplink_connection::_connection_tx_flush_acks()
{
while (_connection.tx()->ack_avail()) {
_connection.tx()->release_packet(
_connection.tx()->get_acked_packet());
}
}
void Uplink_connection::send_ip(void const *ip_base,
size_t ip_size)
{
Size_guard ip_guard { ip_size };
Ipv4_packet const &ip { Ipv4_packet::cast_from(ip_base, ip_guard) };
if (ip.version() != 4) {
log("Drop packet - IP versions other than 4 not supported");
return;
}
size_t const pkt_size { sizeof(Ethernet_frame) + ip_size };
_send(pkt_size, [&] (void *pkt_base, Size_guard &size_guard)
{
/* create ETH header */
Ethernet_frame &eth {
Ethernet_frame::construct_at(pkt_base, size_guard) };
eth.src(_mac_address);
eth.dst(Ethernet_frame::broadcast());
eth.type(Ethernet_frame::Type::IPV4);
/* add IP packet as payload */
eth.memcpy_to_data((void *)ip_base, ip_size, size_guard);
});
}
void Uplink_connection::notify_peer()
{
if (_notify_peers) {
_notify_peers = false;
_connection.rx()->wakeup();
_connection.tx()->wakeup();
}
}
void Uplink_connection::for_each_rx_packet(Handle_packet_func handle_packet)
{
typename Uplink::Connection::Rx::Sink & rx_sink = *_connection.rx();
for (;;) {
if (!rx_sink.packet_avail() || !rx_sink.ack_slots_free())
break;
Packet_descriptor const packet = rx_sink.peek_packet();
bool const packet_valid = rx_sink.packet_valid(packet)
&& (packet.offset() >= 0);
if (packet_valid) {
void *eth_base { rx_sink.packet_content(packet) };
handle_packet(eth_base, packet.size());
_notify_peers = true;
}
(void)rx_sink.try_get_packet();
rx_sink.try_ack_packet(packet);
}
}
Uplink_connection::Uplink_connection(Env &env,
Allocator &alloc,
Signal_context_capability sigh)
:
_packet_alloc { &alloc },
_connection { env, &_packet_alloc, BUF_SIZE, BUF_SIZE, _mac_address,
"uplink_session" }
{
_connection.rx_channel()->sigh_ready_to_ack(sigh);
_connection.rx_channel()->sigh_packet_avail(sigh);
_connection.tx_channel()->sigh_ack_avail(sigh);
_connection.tx_channel()->sigh_ready_to_submit(sigh);
}

View File

@ -0,0 +1,91 @@
/*
* \brief Network back-end towards private network (unencrypted user packets)
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2022-01-07
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _UPLINK_CONNECTION_H_
#define _UPLINK_CONNECTION_H_
/* os includes */
#include <uplink_session/connection.h>
#include <net/ethernet.h>
#include <nic/packet_allocator.h>
namespace Wireguard {
class Uplink_connection;
}
class Wireguard::Uplink_connection
{
private:
using Handle_packet_func = void (*)(void *buf_base,
Genode::size_t buf_size);
using Packet_descriptor = Uplink::Packet_descriptor;
using Packet_source =
::Uplink::Packet_stream_source<::Uplink::Session::Policy>;
enum { PACKET_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE };
enum { BUF_SIZE = Uplink::Connection::Session::QUEUE_SIZE * PACKET_SIZE };
enum class Send_pkt_result { SUCCEEDED, FAILED };
Nic::Packet_allocator _packet_alloc;
Net::Mac_address const _mac_address { 2 };
Uplink::Connection _connection;
bool _notify_peers { true };
bool const _verbose { true };
bool const _verbose_pkt_drop { true };
void _connection_tx_flush_acks();
template <typename WRITE_TO_PACKET_FUNC>
Send_pkt_result _send(Genode::size_t pkt_size,
WRITE_TO_PACKET_FUNC && write_to_pkt)
{
try {
Uplink::Packet_descriptor pkt { _connection.tx()->alloc_packet(pkt_size) };
void *const pkt_base { _connection.tx()->packet_content(pkt) };
Net::Size_guard size_guard { pkt_size };
write_to_pkt(pkt_base, size_guard);
_connection_tx_flush_acks();
_connection.tx()->submit_packet(pkt);
}
catch (Packet_source::Packet_alloc_failed) {
if (_verbose) {
Genode::log(
"Failed sending uplink packet - Failed allocating packet");
}
return Send_pkt_result::FAILED;
}
return Send_pkt_result::SUCCEEDED;
}
public:
Uplink_connection(Genode::Env &env,
Genode::Allocator &alloc,
Genode::Signal_context_capability sigh);
void for_each_rx_packet(Handle_packet_func handle_packet);
void notify_peer();
void send_ip(void const *ip_base,
Genode::size_t ip_size);
};
#endif /* _UPLINK_CONNECTION_H_ */

View File

@ -95,3 +95,4 @@ vm_stress_vbox5-debian32
vm_stress_vbox5-debian64
vmm_arm
vmm_x86
wg_fetchurl