Add support for multiple interfaces

- Smoltcp now talk to a IP device that does the routing
- Add RouteTable
- Add trait LinkDevice representing devices (eth0, loopback...)
- Remove old device
This commit is contained in:
Gartox
2023-09-04 10:11:02 +02:00
parent d47cdbf1fe
commit 0b2b4e41c3
16 changed files with 1337 additions and 333 deletions
Generated
+436 -96
View File
@@ -2,11 +2,35 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "arg_parser"
version = "0.1.0"
source = "git+https://gitlab.redox-os.org/redox-os/arg-parser.git#1c434b55f3e1a0375ebcca85b3e88db7378e82fa"
[[package]]
name = "atomic-polyfill"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28"
dependencies = [
"critical-section",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@@ -19,6 +43,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
[[package]]
name = "byteorder"
version = "0.5.3"
@@ -31,6 +61,15 @@ version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
@@ -43,6 +82,33 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"time",
"wasm-bindgen",
"windows-targets",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]]
name = "critical-section"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
[[package]]
name = "crossbeam-channel"
version = "0.5.8"
@@ -62,6 +128,38 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "defmt"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8a2d011b2fee29fb7d659b83c43fce9a2cb4df453e16d441a51448e448f3f98"
dependencies = [
"bitflags",
"defmt-macros",
]
[[package]]
name = "defmt-macros"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54f0216f6c5acb5ae1a47050a6645024e6edafc2ee32d421955eccfef12ef92e"
dependencies = [
"defmt-parser",
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.29",
]
[[package]]
name = "defmt-parser"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "269924c02afd7f94bc4cecbfa5c379f6ffcf9766b3408fe63d22c728654eccd0"
dependencies = [
"thiserror",
]
[[package]]
name = "dns-parser"
version = "0.7.1"
@@ -73,25 +171,49 @@ dependencies = [
]
[[package]]
name = "extra"
version = "0.1.0"
source = "git+https://gitlab.redox-os.org/redox-os/libextra.git#cf213969493db8667052a591e32a1e26d43c4234"
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
name = "hash32"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
dependencies = [
"bitflags",
"fuchsia-zircon-sys",
"byteorder 1.4.3",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
name = "heapless"
version = "0.7.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743"
dependencies = [
"atomic-polyfill",
"hash32",
"rustc_version",
"spin",
"stable_deref_trait",
]
[[package]]
name = "iana-time-zone"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "idna"
@@ -105,30 +227,14 @@ dependencies = [
]
[[package]]
name = "iovec"
version = "0.1.4"
name = "js-sys"
version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
dependencies = [
"libc",
"wasm-bindgen",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
dependencies = [
"winapi 0.2.8",
"winapi-build",
]
[[package]]
name = "lazycell"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef"
[[package]]
name = "libc"
version = "0.2.147"
@@ -136,12 +242,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "log"
version = "0.3.9"
name = "lock_api"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
"log 0.4.20",
"autocfg",
"scopeguard",
]
[[package]]
@@ -152,9 +259,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "managed"
version = "0.7.2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75de51135344a4f8ed3cfe2720dc27736f7711989703a0b43aadf3753c55577"
checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d"
[[package]]
name = "matches"
@@ -162,36 +269,6 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
[[package]]
name = "mio"
version = "0.6.14"
source = "git+https://gitlab.redox-os.org/redox-os/mio.git?branch=redox-unix#c9a70849ced97387e2607c9c466d23b130ec8901"
dependencies = [
"fuchsia-zircon",
"fuchsia-zircon-sys",
"iovec",
"kernel32-sys",
"lazycell",
"libc",
"log 0.4.20",
"miow",
"net2",
"slab",
"winapi 0.2.8",
]
[[package]]
name = "miow"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
dependencies = [
"kernel32-sys",
"net2",
"winapi 0.2.8",
"ws2_32-sys",
]
[[package]]
name = "net2"
version = "0.2.37"
@@ -199,24 +276,22 @@ source = "git+https://gitlab.redox-os.org/redox-os/net2-rs.git?branch=master#db0
dependencies = [
"cfg-if 0.1.10",
"libc",
"winapi 0.3.9",
"winapi",
]
[[package]]
name = "netutils"
version = "0.1.0"
source = "git+https://gitlab.redox-os.org/redox-os/netutils.git?branch=redox-unix#105ed1ea43413a91152b289fbe76e7efc996e933"
source = "git+https://gitlab.redox-os.org/redox-os/netutils.git#fc11b9bb3c1f5eefccb93ae670e4ec8b3d6fad4f"
dependencies = [
"arg_parser",
"extra",
"libc",
"mio",
"net2",
"ntpclient",
"pbr",
"redox-daemon",
"redox_event",
"redox_syscall 0.2.16",
"redox_syscall 0.3.5",
"redox_termios",
"termion",
"url",
@@ -231,12 +306,27 @@ dependencies = [
"time",
]
[[package]]
name = "num-traits"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
dependencies = [
"autocfg",
]
[[package]]
name = "numtoa"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
[[package]]
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "pbr"
version = "1.1.1"
@@ -245,7 +335,7 @@ checksum = "ed5827dfa0d69b6c92493d6c38e633bbaa5937c153d0d7c28bf12313f8c6d514"
dependencies = [
"crossbeam-channel",
"libc",
"winapi 0.3.9",
"winapi",
]
[[package]]
@@ -254,12 +344,54 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.109",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox-daemon"
version = "0.1.1"
@@ -270,6 +402,18 @@ dependencies = [
"redox_syscall 0.3.5",
]
[[package]]
name = "redox-log"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf6d33a003a5c0b94ec11f10c7c797303f236592964ddb1bfb93e1b438a1557"
dependencies = [
"chrono",
"log",
"smallvec",
"termion",
]
[[package]]
name = "redox_event"
version = "0.1.0"
@@ -284,9 +428,10 @@ version = "0.1.0"
dependencies = [
"byteorder 1.4.3",
"dns-parser",
"log 0.3.9",
"log",
"netutils",
"redox-daemon",
"redox-log",
"redox_event",
"redox_syscall 0.3.5",
"smoltcp",
@@ -320,23 +465,83 @@ dependencies = [
]
[[package]]
name = "slab"
version = "0.4.9"
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"autocfg",
"semver",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
[[package]]
name = "smallvec"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]]
name = "smoltcp"
version = "0.5.0"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d2e3a36ac8fea7b94e666dfa3871063d6e0a5c9d5d4fec9a1a6b7b6760f0229"
dependencies = [
"bitflags",
"byteorder 1.4.3",
"cfg-if 1.0.0",
"defmt",
"heapless",
"log",
"managed",
]
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termion"
version = "1.5.6"
@@ -349,6 +554,26 @@ dependencies = [
"redox_termios",
]
[[package]]
name = "thiserror"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.29",
]
[[package]]
name = "time"
version = "0.1.45"
@@ -357,7 +582,7 @@ checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc",
"wasi",
"winapi 0.3.9",
"winapi",
]
[[package]]
@@ -381,6 +606,12 @@ version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]]
name = "unicode-ident"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
@@ -401,6 +632,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
@@ -408,10 +645,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "winapi"
version = "0.2.8"
name = "wasm-bindgen"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.29",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.29",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
[[package]]
name = "winapi"
@@ -423,12 +708,6 @@ dependencies = [
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
@@ -442,11 +721,72 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "ws2_32-sys"
version = "0.2.1"
name = "windows"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
"winapi 0.2.8",
"winapi-build",
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[patch.unused]]
name = "mio"
version = "0.6.14"
source = "git+https://gitlab.redox-os.org/redox-os/mio.git?branch=redox-unix#c9a70849ced97387e2607c9c466d23b130ec8901"
+3 -2
View File
@@ -27,16 +27,17 @@ dns-parser = "0.7.1"
[dependencies.log]
version = "0.4"
default-features = false
features = ["release_max_level_warn"]
features = ["release_max_level_debug"]
[dependencies.smoltcp]
version = "0.10.0"
default-features = false
features = [
"std",
"medium-ethernet",
"medium-ethernet", "medium-ip",
"proto-ipv4",
"socket-raw", "socket-icmp", "socket-udp", "socket-tcp",
"iface-max-addr-count-8",
"log"
]
#For debugging: "log", "verbose"
-123
View File
@@ -1,123 +0,0 @@
use smoltcp;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::fs::File;
use std::io::Write;
use std::rc::Rc;
use smoltcp::time::Instant;
use smoltcp::wire::EthernetAddress;
use crate::buffer_pool::{Buffer, BufferPool};
struct NetworkDeviceData {
network_file: Rc<RefCell<File>>,
input_queue: Rc<RefCell<VecDeque<Buffer>>>,
local_hwaddr: smoltcp::wire::EthernetAddress,
buffer_pool: Rc<RefCell<BufferPool>>,
}
pub struct NetworkDevice {
data: Rc<RefCell<NetworkDeviceData>>,
}
impl NetworkDevice {
pub const MTU: usize = 1520;
pub fn new(
network_file: Rc<RefCell<File>>,
input_queue: Rc<RefCell<VecDeque<Buffer>>>,
local_hwaddr: smoltcp::wire::EthernetAddress,
buffer_pool: Rc<RefCell<BufferPool>>,
) -> NetworkDevice {
NetworkDevice {
data: Rc::new(RefCell::new(NetworkDeviceData {
network_file,
input_queue,
local_hwaddr,
buffer_pool,
})),
}
}
}
pub struct RxToken {
buffer: Buffer,
}
impl smoltcp::phy::RxToken for RxToken {
fn consume<R, F>(mut self, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R,
{
f(&mut self.buffer)
}
}
pub struct TxToken {
data: Rc<RefCell<NetworkDeviceData>>,
}
impl smoltcp::phy::TxToken for TxToken {
fn consume<R, F>(self, len: usize, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R,
{
let data = self.data.borrow_mut();
let mut buffer = data.buffer_pool.borrow_mut().get_buffer();
buffer.resize(len);
let res = f(&mut buffer);
let mut loopback = false;
if let Ok(mut frame) = smoltcp::wire::EthernetFrame::new_checked(&mut buffer) {
if frame.dst_addr() == EthernetAddress::default() {
frame.set_dst_addr(data.local_hwaddr);
loopback = true;
}
}
if loopback {
data.input_queue.borrow_mut().push_back(buffer.move_out());
} else {
// TODO: Handle error
data.network_file
.borrow_mut()
.write(&buffer);
}
res
}
}
impl smoltcp::phy::Device for NetworkDevice {
type RxToken<'a> = RxToken;
type TxToken<'a> = TxToken;
fn capabilities(&self) -> smoltcp::phy::DeviceCapabilities {
let mut limits = smoltcp::phy::DeviceCapabilities::default();
limits.max_transmission_unit = Self::MTU;
limits.max_burst_size = Some(20);
limits
}
fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
let data = self.data.borrow_mut();
let buffer = data.input_queue.borrow_mut().pop_front();
if let Some(buffer) = buffer {
Some((
RxToken { buffer },
TxToken {
data: Rc::clone(&self.data),
},
))
} else {
None
}
}
fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
Some(TxToken {
data: Rc::clone(&self.data),
})
}
}
+355
View File
@@ -0,0 +1,355 @@
use std::collections::btree_map::Entry;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::{ErrorKind, Read, Write};
use std::rc::Rc;
use smoltcp::storage::PacketMetadata;
use smoltcp::time::{Duration, Instant};
use smoltcp::wire::{
ArpOperation, ArpPacket, ArpRepr, EthernetAddress, EthernetFrame, EthernetProtocol,
EthernetRepr, IpAddress, Ipv4Address, Ipv4Cidr,
};
use super::LinkDevice;
struct Neighbor {
hardware_address: EthernetAddress,
expires_at: Instant,
}
#[derive(Debug, Default)]
enum ArpState {
#[default]
Discovered,
Discovering {
target: Ipv4Address,
tries: u32,
silent_until: Instant,
},
}
type PacketBuffer = smoltcp::storage::PacketBuffer<'static, IpAddress>;
pub struct EthernetLink {
name: Rc<str>,
neighbor_cache: BTreeMap<IpAddress, Neighbor>,
arp_state: ArpState,
waiting_packets: PacketBuffer,
input_buffer: Vec<u8>,
output_buffer: Vec<u8>,
network_file: File,
hardware_address: EthernetAddress,
ip_address: Ipv4Cidr,
}
impl EthernetLink {
// TODO: Review these constants
const MAX_WAITING_PACKET_COUNT: usize = 10;
const MTU: usize = 1500;
const WAITING_PACKET_BUFFER_SIZE: usize = Self::MTU * Self::MAX_WAITING_PACKET_COUNT;
const NEIGHBOR_LIVE_TIME: Duration = Duration::from_secs(60);
const ARP_SILENCE_TIME: Duration = Duration::from_secs(1);
pub fn new(
name: &str,
network_file: File,
hardware_address: EthernetAddress,
ip_address: Ipv4Cidr,
) -> Self {
let waiting_packets = PacketBuffer::new(
vec![PacketMetadata::EMPTY; Self::MAX_WAITING_PACKET_COUNT],
vec![0u8; Self::WAITING_PACKET_BUFFER_SIZE],
);
Self {
name: name.into(),
network_file,
waiting_packets,
hardware_address,
ip_address,
input_buffer: vec![0u8; Self::MTU],
output_buffer: Vec::with_capacity(Self::MTU),
arp_state: Default::default(),
neighbor_cache: Default::default(),
}
}
fn send_to<F>(&mut self, dst: EthernetAddress, size: usize, f: F, proto: EthernetProtocol)
where
F: FnOnce(&mut [u8]),
{
let repr = EthernetRepr {
src_addr: self.hardware_address,
dst_addr: dst,
ethertype: proto,
};
self.output_buffer.clear();
self.output_buffer.resize(repr.buffer_len() + size, 0);
let mut frame = EthernetFrame::new_unchecked(&mut self.output_buffer);
repr.emit(&mut frame);
f(frame.payload_mut());
if let Err(_) = self.network_file.write_all(&self.output_buffer) {
error!(
"Dropped outboud packet on {} (failed to write to network file)",
self.name
)
}
}
fn process_arp(&mut self, packet: &[u8], now: Instant) {
let Ok(repr) = ArpPacket::new_checked(packet).and_then(|packet| ArpRepr::parse(&packet)) else {
debug!("Dropped incomming arp packet on {} (Malformed)", self.name);
return;
};
match repr {
ArpRepr::EthernetIpv4 {
operation,
source_hardware_addr,
source_protocol_addr,
target_hardware_addr,
target_protocol_addr,
} => {
if self.hardware_address != target_hardware_addr {
// Only process packet that are for us
return;
}
if let ArpOperation::Unknown(_) = operation {
return;
}
if !source_hardware_addr.is_unicast() || !source_protocol_addr.is_unicast() {
return;
}
if !self.ip_address.contains_addr(&target_protocol_addr) {
return;
}
self.neighbor_cache.insert(
IpAddress::Ipv4(source_protocol_addr),
Neighbor {
hardware_address: source_hardware_addr,
expires_at: now + Self::NEIGHBOR_LIVE_TIME,
},
);
if let ArpOperation::Request = operation {
let response = ArpRepr::EthernetIpv4 {
operation: ArpOperation::Reply,
source_hardware_addr: self.hardware_address,
source_protocol_addr: self.ip_address.address(),
target_hardware_addr: source_hardware_addr,
target_protocol_addr: source_protocol_addr,
};
self.send_to(
source_hardware_addr,
response.buffer_len(),
|buf| response.emit(&mut ArpPacket::new_unchecked(buf)),
EthernetProtocol::Arp,
);
}
self.check_waiting_packets(source_protocol_addr, source_hardware_addr, now);
}
_ => {}
}
}
fn check_waiting_packets(&mut self, ip: Ipv4Address, mac: EthernetAddress, now: Instant) {
let mut waiting_packets =
std::mem::replace(&mut self.waiting_packets, PacketBuffer::new(vec![], vec![]));
loop {
match waiting_packets.peek() {
Ok((IpAddress::Ipv4(dst), _)) if dst == &ip => {}
Ok((IpAddress::Ipv4(dst), _)) => {
self.arp_state = ArpState::Discovering {
target: *dst,
tries: 0,
silent_until: Instant::ZERO,
};
self.send_arp(now);
break;
}
Err(_) => {
self.arp_state = ArpState::Discovered;
break;
}
}
let (_, packet) = waiting_packets.dequeue().unwrap();
self.send_to(
mac,
packet.len(),
|buf| buf.copy_from_slice(packet),
EthernetProtocol::Ipv4,
);
}
self.waiting_packets = waiting_packets;
}
fn drop_waiting_packets(&mut self, ip: Ipv4Address, now: Instant) {
loop {
match self.waiting_packets.peek() {
Ok((IpAddress::Ipv4(dst), _)) if dst == &ip => {}
Ok((IpAddress::Ipv4(dst), _)) => {
self.arp_state = ArpState::Discovering {
target: *dst,
tries: 0,
silent_until: Instant::ZERO,
};
self.send_arp(now);
return;
}
Err(_) => {
self.arp_state = ArpState::Discovered;
return;
}
}
let _ = self.waiting_packets.dequeue();
debug!(
"Dropped packet on {} because neighbor was not found",
self.name
)
}
}
fn handle_missing_neighbor(&mut self, next_hop: IpAddress, packet: &[u8], now: Instant) {
let Ok(buf) = self.waiting_packets.enqueue(packet.len(), next_hop) else {
warn!("Dropped packet on {} because waiting queue was full", self.name);
return;
};
buf.copy_from_slice(packet);
let IpAddress::Ipv4(next_hop) = next_hop;
if let ArpState::Discovered = self.arp_state {
self.arp_state = ArpState::Discovering {
target: next_hop,
tries: 0,
silent_until: Instant::ZERO,
};
self.send_arp(now)
}
}
fn send_arp(&mut self, now: Instant) {
match self.arp_state {
ArpState::Discovered => {}
ArpState::Discovering { silent_until, .. } if silent_until > now => {}
ArpState::Discovering { target, tries, .. } if tries >= 3 => {
self.drop_waiting_packets(target, now)
}
ArpState::Discovering {
target,
ref mut tries,
ref mut silent_until,
} => {
let arp_repr = ArpRepr::EthernetIpv4 {
operation: ArpOperation::Request,
source_hardware_addr: self.hardware_address,
source_protocol_addr: self.ip_address.address(),
target_hardware_addr: EthernetAddress::BROADCAST,
target_protocol_addr: target,
};
*tries += 1;
*silent_until = now + Self::ARP_SILENCE_TIME;
self.send_to(
EthernetAddress::BROADCAST,
arp_repr.buffer_len(),
|buf| arp_repr.emit(&mut ArpPacket::new_unchecked(buf)),
EthernetProtocol::Arp,
);
}
}
}
}
impl LinkDevice for EthernetLink {
fn send(&mut self, next_hop: IpAddress, packet: &[u8], now: Instant) {
let local_broadcast = match self.ip_address.broadcast() {
Some(addr) => IpAddress::Ipv4(addr) == next_hop,
None => false
};
if local_broadcast || next_hop.is_broadcast() {
self.send_to(
EthernetAddress::BROADCAST,
packet.len(),
|buf| buf.copy_from_slice(packet),
EthernetProtocol::Ipv4,
);
return;
}
match self.neighbor_cache.entry(next_hop) {
Entry::Vacant(_) => self.handle_missing_neighbor(next_hop, packet, now),
Entry::Occupied(e) => {
if e.get().expires_at < now {
e.remove();
self.handle_missing_neighbor(next_hop, packet, now)
} else {
let mac = e.get().hardware_address;
self.send_to(
mac,
packet.len(),
|buf| buf.copy_from_slice(packet),
EthernetProtocol::Ipv4,
)
}
}
}
}
fn recv(&mut self, now: Instant) -> Option<&[u8]> {
let mut input_buffer = std::mem::replace(&mut self.input_buffer, Vec::new());
loop {
if let Err(e) = self.network_file.read(&mut input_buffer) {
if e.kind() != ErrorKind::WouldBlock {
error!("Failed to read ethernet device on link {}", self.name);
} else {
// No packet to read but we check if we have arp to send
self.send_arp(now);
}
self.input_buffer = input_buffer;
return None;
}
let packet = EthernetFrame::new_unchecked(&input_buffer[..]);
let Ok(repr) = EthernetRepr::parse(&packet) else {
debug!("Dropped incomming frame on {} (Malformed)", self.name);
continue;
};
if !repr.dst_addr.is_broadcast() && repr.dst_addr != self.hardware_address {
// Drop packets which are not for us
continue;
}
match repr.ethertype {
EthernetProtocol::Ipv4 => {
self.input_buffer = input_buffer;
return Some(EthernetFrame::new_unchecked(&self.input_buffer[..]).payload());
}
EthernetProtocol::Arp => self.process_arp(packet.payload(), now),
_ => continue,
}
}
}
fn name(&self) -> &Rc<str> {
&self.name
}
}
+45
View File
@@ -0,0 +1,45 @@
use std::rc::Rc;
use smoltcp::storage::PacketMetadata;
use smoltcp::time::Instant;
use crate::scheme::Smolnetd;
use super::LinkDevice;
pub type PacketBuffer = smoltcp::storage::PacketBuffer<'static, ()>;
pub struct LoopbackDevice {
name: Rc<str>,
buffer: PacketBuffer,
}
impl Default for LoopbackDevice {
fn default() -> Self {
let buffer = PacketBuffer::new(
vec![PacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE],
vec![0u8; 1500 * Smolnetd::SOCKET_BUFFER_SIZE],
);
LoopbackDevice {
name: "loopback".into(),
buffer,
}
}
}
impl LinkDevice for LoopbackDevice {
fn send(&mut self, _next_hop: smoltcp::wire::IpAddress, packet: &[u8], _now: Instant) {
match self.buffer.enqueue(packet.len(), ()) {
Err(_) => warn!("loopback dropped packet because buffer was full"),
Ok(buf) => buf.copy_from_slice(packet),
}
}
fn recv(&mut self, _now: Instant) -> Option<&[u8]> {
self.buffer.dequeue().ok().map(|((), buf)| &*buf)
}
fn name(&self) -> &std::rc::Rc<str> {
&self.name
}
}
+57
View File
@@ -0,0 +1,57 @@
pub mod loopback;
pub mod ethernet;
use std::rc::Rc;
use smoltcp::time::Instant;
use smoltcp::wire::IpAddress;
/// Represent a link layer device (eth0, loopback...)
pub trait LinkDevice {
/// Send the given packet to the machine with the `next_hop` ip address
/// This method cannot fail so it's the implementor responsability
/// to buffer packets which can't be sent immediatly or decide to
/// drop them if necessary
fn send(&mut self, next_hop: IpAddress, packet: &[u8], now: Instant);
/// Returns None if nothing is received.
/// Returns an Ip packet otherwise
fn recv(&mut self, now: Instant) -> Option<&[u8]>;
/// Returns the LinkDevice display name used to refer to it and for lookups
fn name(&self) -> &Rc<str>;
}
#[derive(Default)]
pub struct DeviceList {
inner: Vec<Box<dyn LinkDevice>>,
}
impl DeviceList {
pub fn push<T: LinkDevice + 'static>(&mut self, dev: T) {
self.inner.push(Box::new(dev))
}
pub fn get(&self, device_name: &str) -> Option<&dyn LinkDevice> {
self.inner
.iter()
.find(|dev| dev.name().as_ref() == device_name)
.map(|device| device.as_ref())
}
pub fn get_mut(&mut self, device_name: &str) -> Option<&mut (dyn LinkDevice + 'static)> {
self.inner
.iter_mut()
.find(|dev| dev.name().as_ref() == device_name)
.map(|device| device.as_mut())
}
pub fn iter(&self) -> impl Iterator<Item = &(dyn LinkDevice + 'static)> {
self.inner.iter().map(|b| b.as_ref())
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut (dyn LinkDevice + 'static)> {
self.inner.iter_mut().map(|b| b.as_mut())
}
}
+7 -5
View File
@@ -3,11 +3,11 @@
extern crate event;
#[macro_use]
extern crate log;
extern crate byteorder;
extern crate netutils;
extern crate redox_netstack;
extern crate smoltcp;
extern crate syscall;
extern crate byteorder;
use std::cell::RefCell;
use std::fs::File;
@@ -15,14 +15,15 @@ use std::os::unix::io::{FromRawFd, RawFd};
use std::process;
use std::rc::Rc;
use event::EventQueue;
use redox_netstack::error::{Error, Result};
use redox_netstack::logger;
use event::EventQueue;
use scheme::Smolnetd;
mod buffer_pool;
mod device;
mod link;
mod port_set;
mod router;
mod scheme;
fn run(daemon: redox_daemon::Daemon) -> Result<()> {
@@ -143,7 +144,7 @@ fn run(daemon: redox_daemon::Daemon) -> Result<()> {
event_queue.trigger_all(event::Event {
fd: 0,
flags: EventFlags::empty()
flags: EventFlags::empty(),
})?;
event_queue.run()
@@ -158,5 +159,6 @@ fn main() {
process::exit(1);
}
process::exit(0);
}).expect("smoltcp: failed to daemonize");
})
.expect("smoltcp: failed to daemonize");
}
+187
View File
@@ -0,0 +1,187 @@
use std::cell::RefCell;
use std::rc::Rc;
use smoltcp::phy::{Device, DeviceCapabilities, Medium};
use smoltcp::storage::PacketMetadata;
use smoltcp::time::Instant;
use smoltcp::wire::IpAddress;
use self::route_table::RouteTable;
use crate::link::DeviceList;
use crate::scheme::Smolnetd;
pub mod route_table;
pub type PacketBuffer = smoltcp::storage::PacketBuffer<'static, ()>;
pub struct Router {
rx_buffer: PacketBuffer,
tx_buffer: PacketBuffer,
devices: Rc<RefCell<DeviceList>>,
route_table: Rc<RefCell<RouteTable>>,
}
impl Router {
pub fn new(devices: Rc<RefCell<DeviceList>>, route_table: Rc<RefCell<RouteTable>>) -> Self {
let rx_buffer = PacketBuffer::new(
vec![PacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE],
vec![0u8; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE],
);
let tx_buffer = PacketBuffer::new(
vec![PacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE],
vec![0u8; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE],
);
Self {
rx_buffer,
tx_buffer,
devices,
route_table,
}
}
pub const MTU: usize = 1486;
pub fn poll(&mut self, now: Instant) {
self.dispatch_outgoing(now);
self.process_incoming(now);
}
fn process_incoming(&mut self, now: Instant) {
for dev in self.devices.borrow_mut().iter_mut() {
if self.rx_buffer.is_full() {
break;
}
loop {
if self.rx_buffer.is_full() {
break;
}
let Some(buf) = dev.recv(now) else {
break;
};
self.rx_buffer
.enqueue(buf.len(), ())
.expect("We checked if it was full")
.copy_from_slice(buf);
}
}
}
fn dispatch_outgoing(&mut self, now: Instant) {
while let Ok(((), packet)) = self.tx_buffer.dequeue() {
if let Ok(mut packet) = smoltcp::wire::Ipv4Packet::new_checked(packet) {
let dst_addr = IpAddress::Ipv4(packet.dst_addr());
if packet.dst_addr().is_broadcast() {
let buf = packet.into_inner();
for dev in self.devices.borrow_mut().iter_mut() {
dev.send(dst_addr, buf, now)
}
} else {
let route_table = self.route_table.borrow();
let Some(rule) = route_table.lookup_rule(&dst_addr) else {
warn!("No route found for destination: {}", dst_addr);
continue;
};
let next_hop = match rule.via {
Some(via) => via,
None => dst_addr,
};
let mut devices = self.devices.borrow_mut();
let Some(dev) = devices.get_mut(&rule.dev) else {
warn!("Device {} not found", rule.dev);
// TODO: Remove route if device doesn't exist anymore ?
continue;
};
let IpAddress::Ipv4(src) = rule.src;
if src != packet.src_addr() {
packet.set_src_addr(src);
packet.fill_checksum()
}
dev.send(next_hop, packet.into_inner(), now);
}
}
}
}
}
impl Device for Router {
type RxToken<'a> = RxToken<'a>;
type TxToken<'a> = TxToken<'a>;
fn receive(
&mut self,
_timestamp: smoltcp::time::Instant,
) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
if self.rx_buffer.is_empty() || self.tx_buffer.is_full() {
None
} else {
Some((
RxToken {
rx_buffer: &mut self.rx_buffer,
},
TxToken {
tx_buffer: &mut self.tx_buffer,
},
))
}
}
fn transmit(&mut self, _timestamp: smoltcp::time::Instant) -> Option<Self::TxToken<'_>> {
if self.tx_buffer.is_full() {
None
} else {
Some(TxToken {
tx_buffer: &mut self.tx_buffer,
})
}
}
fn capabilities(&self) -> smoltcp::phy::DeviceCapabilities {
let mut caps = DeviceCapabilities::default();
caps.medium = Medium::Ip;
caps.max_transmission_unit = Router::MTU;
caps.max_burst_size = Some(Smolnetd::SOCKET_BUFFER_SIZE);
caps
}
}
pub struct TxToken<'a> {
tx_buffer: &'a mut PacketBuffer,
}
impl smoltcp::phy::TxToken for TxToken<'_> {
fn consume<R, F>(self, len: usize, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R,
{
f(self
.tx_buffer
.enqueue(len, ())
.expect("This was checked before creating the TxToken"))
}
}
pub struct RxToken<'a> {
rx_buffer: &'a mut PacketBuffer,
}
impl<'a> smoltcp::phy::RxToken for RxToken<'a> {
fn consume<R, F>(self, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R,
{
let ((), buf) = self
.rx_buffer
.dequeue()
.expect("This was checked before creating the RxToken");
f(buf)
}
}
+55
View File
@@ -0,0 +1,55 @@
use std::rc::Rc;
use smoltcp::wire::{IpAddress, IpCidr};
#[derive(Debug)]
pub struct Rule {
pub filter: IpCidr,
pub via: Option<IpAddress>,
pub dev: Rc<str>,
pub src: IpAddress,
}
impl Rule {
pub fn new(filter: IpCidr, via: Option<IpAddress>, dev: Rc<str>, src: IpAddress) -> Self {
Self {
filter,
via,
dev,
src,
}
}
}
#[derive(Debug, Default)]
pub struct RouteTable {
rules: Vec<Rule>,
}
impl RouteTable {
pub fn lookup_rule(&self, dst: &IpAddress) -> Option<&Rule> {
self.rules
.iter()
.rev()
.find(|rule| rule.filter.contains_addr(dst))
}
pub fn lookup_src_addr(&self, dst: &IpAddress) -> Option<IpAddress> {
Some(self.lookup_rule(dst)?.src)
}
pub fn lookup_gateway(&self, dst: &IpAddress) -> Option<IpAddress> {
self.lookup_rule(dst)?.via
}
pub fn insert_rule(&mut self, new_rule: Rule) {
let i = match self
.rules
.binary_search_by_key(&new_rule.filter.prefix_len(), |rule| {
rule.filter.prefix_len()
}) {
Ok(i) | Err(i) => i,
};
self.rules.insert(i, new_rule);
}
}
+8 -8
View File
@@ -7,10 +7,10 @@ use syscall::{Error as SyscallError, Result as SyscallResult};
use syscall;
use byteorder::{ByteOrder, NetworkEndian};
use crate::device::NetworkDevice;
use crate::port_set::PortSet;
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
use super::{Smolnetd, SocketSet, Interface};
use crate::router::Router;
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme, Context};
use super::{Smolnetd, SocketSet};
pub type IcmpScheme = SocketScheme<IcmpSocket<'static>>;
@@ -75,7 +75,7 @@ impl<'a> SchemeSocket for IcmpSocket<'a> {
path: &str,
_uid: u32,
ident_set: &mut Self::SchemeDataT,
iface: &Interface
_context: &Context
) -> SyscallResult<(SocketHandle, Self::DataT)> {
use std::str::FromStr;
@@ -95,11 +95,11 @@ impl<'a> SchemeSocket for IcmpSocket<'a> {
let socket = IcmpSocket::new(
IcmpSocketBuffer::new(
vec![IcmpPacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE],
vec![0; NetworkDevice::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
vec![0; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
),
IcmpSocketBuffer::new(
vec![IcmpPacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE],
vec![0; NetworkDevice::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
vec![0; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
)
);
let handle = socket_set.add(socket);
@@ -127,11 +127,11 @@ impl<'a> SchemeSocket for IcmpSocket<'a> {
let socket = IcmpSocket::new(
IcmpSocketBuffer::new(
vec![IcmpPacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE],
vec![0; NetworkDevice::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
vec![0; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
),
IcmpSocketBuffer::new(
vec![IcmpPacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE],
vec![0; NetworkDevice::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
vec![0; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
)
);
let handle = socket_set.add(socket);
+7 -6
View File
@@ -5,9 +5,10 @@ use std::str;
use syscall::{Error as SyscallError, Result as SyscallResult};
use syscall;
use crate::device::NetworkDevice;
use super::{Smolnetd, SocketSet, Interface};
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
use crate::router::Router;
use super::{Smolnetd, SocketSet};
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme, Context};
pub type IpScheme = SocketScheme<RawSocket<'static>>;
@@ -59,7 +60,7 @@ impl<'a> SchemeSocket for RawSocket<'a> {
path: &str,
uid: u32,
_: &mut Self::SchemeDataT,
iface: &Interface
_context: &Context
) -> SyscallResult<(SocketHandle, Self::DataT)> {
if uid != 0 {
return Err(SyscallError::new(syscall::EACCES));
@@ -69,11 +70,11 @@ impl<'a> SchemeSocket for RawSocket<'a> {
let rx_buffer = RawSocketBuffer::new(
vec![RawPacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE],
vec![0; NetworkDevice::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
vec![0; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
);
let tx_buffer = RawSocketBuffer::new(
vec![RawPacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE],
vec![0; NetworkDevice::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
vec![0; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
);
let ip_socket = RawSocket::new(
IpVersion::Ipv4,
+116 -71
View File
@@ -1,35 +1,41 @@
use crate::link::ethernet::EthernetLink;
use crate::link::LinkDevice;
use crate::link::{loopback::LoopbackDevice, DeviceList};
use crate::router::route_table::{RouteTable, Rule};
use crate::router::Router;
use crate::scheme::smoltcp::iface::SocketSet as SmoltcpSocketSet;
use netutils::getcfg;
use smoltcp;
use smoltcp::iface::{Interface as SmoltcpInterface, Routes, Config};
use smoltcp::iface::{Config, Interface as SmoltcpInterface};
use smoltcp::phy::Tracer;
use crate::scheme::smoltcp::iface::SocketSet as SmoltcpSocketSet;
use smoltcp::time::{Duration, Instant};
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address, IpListenEndpoint, HardwareAddress};
use smoltcp::wire::{
EthernetAddress, HardwareAddress, IpAddress, IpCidr, IpListenEndpoint, Ipv4Address, Ipv4Cidr,
};
use std::cell::RefCell;
use std::collections::VecDeque;
use std::fs::File;
use std::io::{self, Read, Write};
use std::io::{Read, Write};
use std::mem::size_of;
use std::rc::Rc;
use std::str::FromStr;
use syscall::data::TimeSpec;
use syscall;
use syscall::data::TimeSpec;
use crate::buffer_pool::{Buffer, BufferPool};
use crate::device::NetworkDevice;
use redox_netstack::error::{Error, Result};
use self::icmp::IcmpScheme;
use self::ip::IpScheme;
use self::netcfg::NetCfgScheme;
use self::tcp::TcpScheme;
use self::udp::UdpScheme;
use self::icmp::IcmpScheme;
use self::netcfg::NetCfgScheme;
use crate::buffer_pool::{Buffer, BufferPool};
use redox_netstack::error::{Error, Result};
mod icmp;
mod ip;
mod netcfg;
mod socket;
mod tcp;
mod udp;
mod icmp;
mod netcfg;
type SocketSet = SmoltcpSocketSet<'static>;
type Interface = Rc<RefCell<SmoltcpInterface>>;
@@ -38,11 +44,12 @@ const MAX_DURATION: Duration = Duration::from_millis(u64::MAX);
const MIN_DURATION: Duration = Duration::from_millis(0);
pub struct Smolnetd {
network_file: Rc<RefCell<File>>,
network_device: Tracer<NetworkDevice>,
router_device: Tracer<Router>,
iface: Interface,
link_devices: Rc<RefCell<DeviceList>>,
route_table: Rc<RefCell<RouteTable>>,
time_file: File,
iface: Interface,
socket_set: Rc<RefCell<SocketSet>>,
timer: ::std::time::Instant,
@@ -57,10 +64,10 @@ pub struct Smolnetd {
}
impl Smolnetd {
const MAX_PACKET_SIZE: usize = 2048;
const SOCKET_BUFFER_SIZE: usize = 128; //packets
const MIN_CHECK_TIMEOUT: Duration = Duration::from_millis(10);
const MAX_CHECK_TIMEOUT: Duration = Duration::from_millis(500);
pub const MAX_PACKET_SIZE: usize = 2048;
pub const SOCKET_BUFFER_SIZE: usize = 128; //packets
pub const MIN_CHECK_TIMEOUT: Duration = Duration::from_millis(10);
pub const MAX_CHECK_TIMEOUT: Duration = Duration::from_millis(500);
pub fn new(
network_file: File,
@@ -79,48 +86,104 @@ impl Smolnetd {
IpCidr::new(local_ip, 24),
IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8),
];
let default_gw = Ipv4Address::from_str(getcfg("ip_router").unwrap().trim())
.expect("Can't parse the 'ip_router' cfg.");
let buffer_pool = Rc::new(RefCell::new(BufferPool::new(Self::MAX_PACKET_SIZE)));
let input_queue = Rc::new(RefCell::new(VecDeque::new()));
let network_file = Rc::new(RefCell::new(network_file));
let mut network_device = Tracer::new(NetworkDevice::new(
Rc::clone(&network_file),
Rc::clone(&input_queue),
hardware_addr,
Rc::clone(&buffer_pool),
), |_timestamp, printer| {
trace!("{}", printer)
});
let config = Config::new(HardwareAddress::Ethernet(hardware_addr));
let devices = Rc::new(RefCell::new(DeviceList::default()));
let route_table = Rc::new(RefCell::new(RouteTable::default()));
let mut network_device = Tracer::new(
Router::new(Rc::clone(&devices), Rc::clone(&route_table)),
|_timestamp, printer| trace!("{}", printer),
);
let config = Config::new(HardwareAddress::Ip);
let mut iface = SmoltcpInterface::new(config, &mut network_device, Instant::now());
iface.update_ip_addrs(|ip_addrs| ip_addrs.extend(protocol_addrs));
iface.routes_mut().add_default_ipv4_route(default_gw).expect("Failed to add default gateway");
iface
.routes_mut()
.add_default_ipv4_route(default_gw)
.expect("Failed to add default gateway");
let iface = Rc::new(RefCell::new(iface));
let socket_set = Rc::new(RefCell::new(SocketSet::new(vec![])));
let loopback = LoopbackDevice::default();
route_table.borrow_mut().insert_rule(Rule::new(
"127.0.0.0/8".parse().unwrap(),
None,
Rc::clone(loopback.name()),
"127.0.0.1".parse().unwrap(),
));
let IpAddress::Ipv4(local_ip) = local_ip;
let eth0 = EthernetLink::new(
"eth0",
network_file,
hardware_addr,
Ipv4Cidr::new(local_ip, 24),
);
route_table.borrow_mut().insert_rule(Rule::new(
IpCidr::new(IpAddress::Ipv4(local_ip), 24),
None,
Rc::clone(eth0.name()),
IpAddress::Ipv4(local_ip),
));
route_table.borrow_mut().insert_rule(Rule::new(
"0.0.0.0/0".parse().unwrap(),
Some(IpAddress::Ipv4(default_gw)),
Rc::clone(eth0.name()),
IpAddress::Ipv4(local_ip),
));
devices.borrow_mut().push(loopback);
devices.borrow_mut().push(eth0);
Smolnetd {
iface: Rc::clone(&iface),
network_device,
router_device: network_device,
route_table: Rc::clone(&route_table),
socket_set: Rc::clone(&socket_set),
timer: ::std::time::Instant::now(),
link_devices: devices,
time_file,
ip_scheme: IpScheme::new(Rc::clone(&iface), Rc::clone(&socket_set), ip_file),
udp_scheme: UdpScheme::new(Rc::clone(&iface), Rc::clone(&socket_set), udp_file),
tcp_scheme: TcpScheme::new(Rc::clone(&iface), Rc::clone(&socket_set), tcp_file),
icmp_scheme: IcmpScheme::new(Rc::clone(&iface), Rc::clone(&socket_set), icmp_file),
ip_scheme: IpScheme::new(
Rc::clone(&iface),
Rc::clone(&route_table),
Rc::clone(&socket_set),
ip_file,
),
udp_scheme: UdpScheme::new(
Rc::clone(&iface),
Rc::clone(&route_table),
Rc::clone(&socket_set),
udp_file,
),
tcp_scheme: TcpScheme::new(
Rc::clone(&iface),
Rc::clone(&route_table),
Rc::clone(&socket_set),
tcp_file,
),
icmp_scheme: IcmpScheme::new(
Rc::clone(&iface),
Rc::clone(&route_table),
Rc::clone(&socket_set),
icmp_file,
),
netcfg_scheme: NetCfgScheme::new(Rc::clone(&iface), netcfg_file),
input_queue,
network_file,
buffer_pool,
}
}
pub fn on_network_scheme_event(&mut self) -> Result<Option<()>> {
if self.read_frames()? > 0 {
self.poll()?;
}
self.poll()?;
Ok(None)
}
@@ -183,22 +246,23 @@ impl Smolnetd {
let mut iter_limit = 10usize;
let mut iface = self.iface.borrow_mut();
let mut socket_set = self.socket_set.borrow_mut();
let timestamp = Instant::from(self.timer);
loop {
let timestamp = Instant::from(self.timer);
if iter_limit == 0 {
break MIN_DURATION;
}
iter_limit -= 1;
// TODO: Check what if the bool returned by poll can be useful
iface.poll(timestamp, &mut self.network_device, &mut socket_set);
self.router_device.get_mut().poll(timestamp);
// TODO: Check what if the bool returned by poll can be useful
iface.poll(timestamp, &mut self.router_device, &mut socket_set);
match iface.poll_delay(timestamp, &socket_set) {
Some(delay) if delay == Duration::ZERO => { }
Some(delay) => {
break ::std::cmp::min(MAX_DURATION, delay)
}
None => break MAX_DURATION
Some(delay) if delay == Duration::ZERO => {}
Some(delay) => break ::std::cmp::min(MAX_DURATION, delay),
None => break MAX_DURATION,
};
}
};
@@ -211,26 +275,6 @@ impl Smolnetd {
))
}
fn read_frames(&mut self) -> Result<usize> {
let mut total_frames = 0;
loop {
let mut buffer = self.buffer_pool.borrow_mut().get_buffer();
let count = match self.network_file.borrow_mut().read(&mut buffer) {
Ok(count) => count,
Err(err) => match err.kind() {
io::ErrorKind::WouldBlock => break,
_ => return Err(
Error::from_io_error(err, "Failed to read from network file")
)
}
};
buffer.resize(count);
self.input_queue.borrow_mut().push_back(buffer);
total_frames += 1;
}
Ok(total_frames)
}
fn notify_sockets(&mut self) -> Result<()> {
self.ip_scheme.notify_sockets()?;
self.udp_scheme.notify_sockets()?;
@@ -257,14 +301,15 @@ fn post_fevent(scheme_file: &mut File, fd: usize, event: usize, data_len: usize)
fn parse_endpoint(socket: &str) -> IpListenEndpoint {
let mut socket_parts = socket.split(':');
let host =
Ipv4Address::from_str(socket_parts.next().unwrap_or("")).ok().filter(|addr| !addr.is_unspecified()).map(IpAddress::Ipv4);
let host = Ipv4Address::from_str(socket_parts.next().unwrap_or(""))
.ok()
.filter(|addr| !addr.is_unspecified())
.map(IpAddress::Ipv4);
let port = socket_parts
.next()
.unwrap_or("")
.parse::<u16>()
.unwrap_or(0);
IpListenEndpoint{ addr: host, port}
IpListenEndpoint { addr: host, port }
}
+3 -2
View File
@@ -158,7 +158,8 @@ fn mk_root_node(iface: Interface, notifier: NotifierRef, dns_config: DNSConfigRe
"mac" => {
rw [iface, notifier] (Option<EthernetAddress>, None)
|| {
format!("{}\n", iface.borrow().hardware_addr())
// format!("{}\n", iface.borrow().hardware_addr())
String::new()
}
|cur_value, line| {
if cur_value.is_none() {
@@ -175,7 +176,7 @@ fn mk_root_node(iface: Interface, notifier: NotifierRef, dns_config: DNSConfigRe
}
|cur_value| {
if let Some(mac) = *cur_value {
iface.borrow_mut().set_hardware_addr(smoltcp::wire::HardwareAddress::Ethernet(mac));
// iface.borrow_mut().set_hardware_addr(smoltcp::wire::HardwareAddress::Ethernet(mac));
notifier.borrow_mut().schedule_notify("ifaces/eth0/mac");
}
Ok(())
+25 -6
View File
@@ -19,12 +19,18 @@ use syscall::{
};
use super::Interface;
use crate::router::route_table::RouteTable;
use crate::scheme::smoltcp::iface::SocketHandle;
use redox_netstack::error::{Error, Result};
use smoltcp::socket::AnySocket;
use super::{post_fevent, SocketSet};
pub struct Context {
pub iface: Interface,
pub route_table: Rc<RefCell<RouteTable>>,
}
pub struct NullFile {
pub flags: usize,
pub uid: u32,
@@ -192,7 +198,7 @@ where
path: &str,
uid: u32,
data: &mut Self::SchemeDataT,
iface: &Interface,
context: &Context,
) -> SyscallResult<(SocketHandle, Self::DataT)>;
fn close_file(
@@ -231,7 +237,7 @@ where
nulls: BTreeMap<usize, NullFile>,
files: BTreeMap<usize, SchemeFile<SocketT>>,
ref_counts: BTreeMap<SocketHandle, usize>,
iface: Interface,
context: Context,
socket_set: Rc<RefCell<SocketSet>>,
scheme_file: File,
wait_queue: WaitQueue,
@@ -245,13 +251,13 @@ where
{
pub fn new(
iface: Interface,
route_table: Rc<RefCell<RouteTable>>,
socket_set: Rc<RefCell<SocketSet>>,
scheme_file: File,
) -> SocketScheme<SocketT> {
SocketScheme {
next_fd: 1,
nulls: BTreeMap::new(),
iface,
files: BTreeMap::new(),
ref_counts: BTreeMap::new(),
socket_set,
@@ -259,6 +265,7 @@ where
scheme_file,
wait_queue: Vec::new(),
_phantom_socket: PhantomData,
context: Context { iface, route_table },
}
}
@@ -514,7 +521,7 @@ where
path,
uid,
&mut self.scheme_data,
&self.iface,
&self.context,
)?;
let file = SchemeFile::Socket(SocketFile {
@@ -606,7 +613,12 @@ where
SchemeFile::Socket(ref mut file) => {
let mut socket_set = self.socket_set.borrow_mut();
let socket = socket_set.get_mut::<SocketT>(file.socket_handle);
return SocketT::write_buf(socket, file, buf);
let ret = SocketT::write_buf(socket, file, buf);
match ret {
Ok(None) => {}
_ => file.write_notified = false,
}
return ret;
}
}
};
@@ -626,7 +638,14 @@ where
SchemeFile::Socket(ref mut file) => {
let mut socket_set = self.socket_set.borrow_mut();
let socket = socket_set.get_mut::<SocketT>(file.socket_handle);
return SocketT::read_buf(socket, file, buf);
let ret = SocketT::read_buf(socket, file, buf);
match ret {
Ok(None) => {}
_ => file.read_notified = false
}
return ret;
}
}
};
+28 -9
View File
@@ -6,8 +6,8 @@ use std::str;
use syscall;
use syscall::{Error as SyscallError, Result as SyscallResult};
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
use super::{parse_endpoint, Interface, SocketSet};
use super::socket::{Context, DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
use super::{parse_endpoint, SocketSet};
use crate::port_set::PortSet;
pub type TcpScheme = SocketScheme<TcpSocket<'static>>;
@@ -62,7 +62,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
path: &str,
uid: u32,
port_set: &mut Self::SchemeDataT,
iface: &Interface,
context: &Context,
) -> SyscallResult<(SocketHandle, Self::DataT)> {
trace!("TCP open {}", path);
let mut parts = path.split('/');
@@ -92,10 +92,27 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
let tcp_socket = socket_set.get_mut::<TcpSocket>(socket_handle);
let listen_enpoint = if remote_endpoint.is_specified() {
let local_endpoint_addr = match local_endpoint.addr {
Some(addr) if !addr.is_unspecified() => Some(addr),
_ => {
let route_table = context.route_table.borrow();
let addr = route_table
.lookup_src_addr(&remote_endpoint.addr.expect("Checked in is_specified"));
if matches!(addr, None) {
error!("Opening a TCP connection with a probably invalid source IP as no route have been found for destination: {}", remote_endpoint);
}
addr
}
};
let local_endpoint = IpListenEndpoint {
addr: local_endpoint_addr,
port: local_endpoint.port,
};
trace!("Connecting tcp {} {}", local_endpoint, remote_endpoint);
tcp_socket
.connect(
iface.borrow_mut().context(),
context.iface.borrow_mut().context(),
IpEndpoint::new(remote_endpoint.addr.unwrap(), remote_endpoint.port),
local_endpoint,
)
@@ -264,11 +281,13 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
data: Some(endpoint),
..
}),
) => if endpoint.is_specified() {
write!(&mut path, "{}", endpoint).unwrap()
} else {
write!(&mut path, "0.0.0.0:{}", endpoint.port).unwrap()
},
) => {
if endpoint.is_specified() {
write!(&mut path, "{}", endpoint).unwrap()
} else {
write!(&mut path, "0.0.0.0:{}", endpoint.port).unwrap()
}
}
_ => path.push_str(unspecified),
}
trace!("fpath: {}", path);
+5 -5
View File
@@ -5,9 +5,9 @@ use std::str;
use syscall::{Error as SyscallError, Result as SyscallResult};
use syscall;
use crate::device::NetworkDevice;
use crate::port_set::PortSet;
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme};
use crate::router::Router;
use super::socket::{DupResult, SchemeFile, SchemeSocket, SocketFile, SocketScheme, Context};
use super::{parse_endpoint, Smolnetd, SocketSet, Interface};
pub type UdpScheme = SocketScheme<UdpSocket<'static>>;
@@ -62,7 +62,7 @@ impl<'a> SchemeSocket for UdpSocket<'a> {
path: &str,
uid: u32,
port_set: &mut Self::SchemeDataT,
_iface: &Interface
_context: &Context
) -> SyscallResult<(SocketHandle, Self::DataT)> {
let mut parts = path.split('/');
let remote_endpoint = parse_endpoint(parts.next().unwrap_or(""));
@@ -74,11 +74,11 @@ impl<'a> SchemeSocket for UdpSocket<'a> {
let rx_buffer = UdpSocketBuffer::new(
vec![UdpPacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE],
vec![0; NetworkDevice::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
vec![0; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
);
let tx_buffer = UdpSocketBuffer::new(
vec![UdpPacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE],
vec![0; NetworkDevice::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
vec![0; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE]
);
let udp_socket = UdpSocket::new(rx_buffer, tx_buffer);