diff --git a/Cargo.lock b/Cargo.lock index dcfb83fd7df..ad42c82ae1e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1105,7 +1105,7 @@ dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "log", @@ -4939,6 +4939,15 @@ dependencies = [ "utcnow", ] +[[package]] +name = "ockam_ebpf" +version = "0.1.0" +source = "git+https://github.com/build-trust/ockam-ebpf.git#3cef6c7b7fe6b27003fb4bb22f88380b9e647af5" +dependencies = [ + "reqwest", + "url", +] + [[package]] name = "ockam_executor" version = "0.89.0" @@ -5117,6 +5126,7 @@ dependencies = [ "minicbor", "nix 0.29.0", "ockam_core", + "ockam_ebpf", "ockam_macros", "ockam_node", "ockam_transport_core", @@ -8623,7 +8633,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -8986,13 +8996,6 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" -[[package]] -name = "xtask" -version = "0.1.0" -dependencies = [ - "clap", -] - [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/Cargo.toml b/Cargo.toml index be181ca4dec..fb034b5285c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,8 +11,6 @@ members = [ "tools/docs/example_test_helper", "tools/stress-test", ] -# See `implementations/rust/ockam/ockam_ebpf/README.md` -exclude = ["implementations/rust/ockam/ockam_ebpf"] # Coverage profile for generating code coverage with grcov. # diff --git a/NOTICE.md b/NOTICE.md index 20479f7c389..47229e78648 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -361,6 +361,7 @@ This file contains attributions for any 3rd-party open source code used in this | objc2-foundation | MIT | https://crates.io/crates/objc2-foundation | | objc_id | MIT | https://crates.io/crates/objc_id | | object | Apache-2.0, MIT | https://crates.io/crates/object | +| ockam_ebpf | Apache-2.0 | https://github.com/build-trust/ockam-ebpf.git | | once_cell | MIT, Apache-2.0 | https://crates.io/crates/once_cell | | onig | MIT | https://crates.io/crates/onig | | onig_sys | MIT | https://crates.io/crates/onig_sys | diff --git a/implementations/rust/ockam/ockam_ebpf/.cargo/config.toml b/implementations/rust/ockam/ockam_ebpf/.cargo/config.toml deleted file mode 100644 index d6b50e798a4..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/.cargo/config.toml +++ /dev/null @@ -1,5 +0,0 @@ -[build] -target = "bpfel-unknown-none" - -[unstable] -build-std = ["core"] diff --git a/implementations/rust/ockam/ockam_ebpf/CHANGELOG.md b/implementations/rust/ockam/ockam_ebpf/CHANGELOG.md deleted file mode 100644 index 82a548c4c37..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/CHANGELOG.md +++ /dev/null @@ -1,39 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## 0.1.0 - 2024-11-12 - -### Added - -- Add `CAP_NET_ADMIN` to ebpf requirements check -- Async read from the rawsocket -- Disable ebpf logs -- Updated dependencies - -## 0.1.0 - 2024-10-23 - -### Added - -- Updated dependencies - -## 0.1.0 - 2024-10-16 - -### Added - -- Fix ebpf non-contiguous memory access -- Updated dependencies - -## 0.1.0 - 2024-09-23 - -### Added - -- Add `ockam_ebpf` -- Updated dependencies - -## v0.1.0 - 2024-08-21 -### Added - - - Initial implementation. diff --git a/implementations/rust/ockam/ockam_ebpf/Cargo.lock b/implementations/rust/ockam/ockam_ebpf/Cargo.lock deleted file mode 100644 index e7234cad7e2..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/Cargo.lock +++ /dev/null @@ -1,189 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aya-ebpf" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8dbaf5409a1a0982e5c9bdc0f499a55fe5ead39fe9c846012053faf0d404f73" -dependencies = [ - "aya-ebpf-bindings", - "aya-ebpf-cty", - "aya-ebpf-macros", - "rustversion", -] - -[[package]] -name = "aya-ebpf-bindings" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783dc1a82a3d71d83286165381dcc1b1d41643f4b110733d135547527c000a9a" -dependencies = [ - "aya-ebpf-cty", -] - -[[package]] -name = "aya-ebpf-cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cce099aaf3abb89f9a1f8594ffe07fa53738ebc2882fac624d10d9ba31a1b10" - -[[package]] -name = "aya-ebpf-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f47f7b4a75eb5f1d7ba0fb5628d247b1cf20388658899177875dabdda66865" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "aya-log-common" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "befef9fe882e63164a2ba0161874e954648a72b0e1c4b361f532d590638c4eec" -dependencies = [ - "num_enum", -] - -[[package]] -name = "aya-log-ebpf" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae348f459df78a79e5cd5e164b6562b927033b97ca3b033605b341a474f44510" -dependencies = [ - "aya-ebpf", - "aya-log-common", - "aya-log-ebpf-macros", -] - -[[package]] -name = "aya-log-ebpf-macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d8251a75f56077db51892041aa6b77c70ef2723845d7a210979700b2f01bc4" -dependencies = [ - "aya-log-common", - "aya-log-parser", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "aya-log-parser" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b102eb5c88c9aa0b49102d3fbcee08ecb0dfa81014f39b373311de7a7032cb" -dependencies = [ - "aya-log-common", -] - -[[package]] -name = "network-types" -version = "0.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e82e9f64c09f56aa7c80c3fa087997bd99a913f91d9c74d36cf5fd75dd5773e6" - -[[package]] -name = "num_enum" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "ockam_ebpf" -version = "0.1.0" -dependencies = [ - "aya-ebpf", - "aya-log-ebpf", - "network-types", -] - -[[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", - "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.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - -[[package]] -name = "syn" -version = "2.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" diff --git a/implementations/rust/ockam/ockam_ebpf/Cargo.toml b/implementations/rust/ockam/ockam_ebpf/Cargo.toml deleted file mode 100644 index ecb3f493711..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -name = "ockam_ebpf" -version = "0.1.0" -authors = ["Ockam Developers"] -categories = ["network-programming"] -edition = "2021" -homepage = "https://github.com/build-trust/ockam" -keywords = ["ockam", "crypto", "p2p", "cryptography", "encryption"] -license = "Apache-2.0" -publish = true -readme = "README.md" -repository = "https://github.com/build-trust/ockam/implementations/rust/ockam/ockam_ebpf" -rust-version = "1.56.0" -description = """ -eBPF program used by Ockam TCP Portals -""" - -[features] -default = [] -logging = ["aya-log-ebpf"] - -[dependencies] -aya-ebpf = "0.1.1" -aya-log-ebpf = { version = "0.1.1", optional = true } -network-types = "0.0.7" - -[[bin]] -name = "ockam_ebpf" -path = "src/entrypoint.rs" - -[profile.dev] -opt-level = 3 -debug = false -debug-assertions = false -overflow-checks = false -lto = true -panic = "abort" -incremental = false -codegen-units = 1 -rpath = false - -[profile.release] -lto = true -panic = "abort" -codegen-units = 1 diff --git a/implementations/rust/ockam/ockam_ebpf/README.md b/implementations/rust/ockam/ockam_ebpf/README.md deleted file mode 100644 index 14dc81b7545..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# ockam_ebpf - -[![crate][crate-image]][crate-link] -[![docs][docs-image]][docs-link] -[![license][license-image]][license-link] -[![discuss][discuss-image]][discuss-link] - -Ockam is a library for building devices that communicate securely, privately -and trustfully with cloud services and other devices. - -This crate contains the eBPF part of Ockam Reliable TCP Portals. - -### Build - -```bash -cargo build-ebpf -``` - -Building eBPFs have roughly following requirements: - - Linux - - Rust nightly - - Some dependencies to be installed - -Because of that crate with the eBPF code is kept out of the workspace. -Example of a virtual machine to build it can be found in `ubuntu_x86.yaml`. - -Using ockam with eBPFs requires: - - Linux - - root (CAP_BPF, CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_ADMIN) - -Example of a virtual machine to run ockam with eBPF can be found in `ubuntu_arm.yaml`. - -eBPF is a small architecture-independent object file that is small enough, -to include it in the repo. - -The built eBPF object should be copied to `/implementations/rust/ockam/ockam_ebpf/ockam_ebpf`, -from where it will be grabbed by `ockam_transport_tcp` crate. - -## Usage - -Add this to your `Cargo.toml`: - -``` -[dependencies] -ockam_ebpf = "0.1.0" -``` - -## License - -This code is licensed under the terms of the [Apache License 2.0][license-link]. - -[main-ockam-crate-link]: https://crates.io/crates/ockam - -[crate-image]: https://img.shields.io/crates/v/ockam_ebpf.svg -[crate-link]: https://crates.io/crates/ockam_ebpf - -[docs-image]: https://docs.rs/ockam_ebpf/badge.svg -[docs-link]: https://docs.rs/ockam_ebpf - -[license-image]: https://img.shields.io/badge/License-Apache%202.0-green.svg -[license-link]: https://github.com/build-trust/ockam/blob/HEAD/LICENSE - -[discuss-image]: https://img.shields.io/badge/Discuss-Github%20Discussions-ff70b4.svg -[discuss-link]: https://github.com/build-trust/ockam/discussions diff --git a/implementations/rust/ockam/ockam_ebpf/ockam_ebpf b/implementations/rust/ockam/ockam_ebpf/ockam_ebpf deleted file mode 100644 index 82c508d31b4..00000000000 Binary files a/implementations/rust/ockam/ockam_ebpf/ockam_ebpf and /dev/null differ diff --git a/implementations/rust/ockam/ockam_ebpf/rust-toolchain.toml b/implementations/rust/ockam/ockam_ebpf/rust-toolchain.toml deleted file mode 100644 index 24ce3918366..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/rust-toolchain.toml +++ /dev/null @@ -1,13 +0,0 @@ -[toolchain] -channel = "nightly" -# The source code of rustc, provided by the rust-src component, is needed for -# building eBPF programs. -components = [ - "cargo", - "clippy", - "rust-docs", - "rust-src", - "rust-std", - "rustc", - "rustfmt", -] diff --git a/implementations/rust/ockam/ockam_ebpf/src/checksum.rs b/implementations/rust/ockam/ockam_ebpf/src/checksum.rs deleted file mode 100644 index 15d29a4d8ff..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/src/checksum.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::checksum_helpers::{checksum, checksum_update_word}; -use aya_ebpf::programs::TcContext; -use network_types::ip::Ipv4Hdr; -use network_types::tcp::TcpHdr; - -#[inline(always)] -pub fn iph_update_csum(ctx: &TcContext, ipv4hdr: *mut Ipv4Hdr) { - unsafe { - let len = (*ipv4hdr).ihl() as usize * 4; - - (*ipv4hdr).check = 0; - - let check = checksum(ipv4hdr as usize, len, ctx.data_end()); - - (*ipv4hdr).check = check; - } -} - -#[inline(always)] -pub fn tcph_update_csum(ipv4hdr: *const Ipv4Hdr, tcphdr: *mut TcpHdr) { - // TODO: Theoretically, removing all big endian conversions will yield the same result. - - unsafe { - // User-space code calculates checksum using 0.0.0.0 as src IP, because it's not known - // at that moment. Here we will update the checksum in respect to the actual src IP value. - let original_check = u16::from_be((*tcphdr).check); - - let actual_ip = (*ipv4hdr).src_addr; - let actual_ip_word1 = u16::from_be((actual_ip & 0xffff) as u16); - let actual_ip_word2 = u16::from_be((actual_ip >> 16) as u16); - - let check = checksum_update_word(original_check, 0, actual_ip_word1); - let check = checksum_update_word(check, 0, actual_ip_word2); - - (*tcphdr).check = check.to_be(); - } -} diff --git a/implementations/rust/ockam/ockam_ebpf/src/checksum_helpers.rs b/implementations/rust/ockam/ockam_ebpf/src/checksum_helpers.rs deleted file mode 100644 index 2d306e78180..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/src/checksum_helpers.rs +++ /dev/null @@ -1,45 +0,0 @@ -/// Compute Internet checksum according to RFC 1071. -pub fn checksum(packet: usize, size: usize, end: usize) -> u16 { - fold(sum(packet, size, end)) -} - -/// Checksum update according to RFC 1624. -pub fn checksum_update_word(original_check: u16, old_word: u16, new_word: u16) -> u16 { - let mut csum = (!original_check) as u64; - csum += (!old_word) as u64; - csum += new_word as u64; - - fold(csum) -} - -/// Converts a checksum into u16 according to 1's complement addition -fn fold(mut csum: u64) -> u16 { - for _i in 0..4 { - if (csum >> 16) > 0 { - csum = (csum & 0xffff) + (csum >> 16); - } - } - !(csum as u16) -} - -/// Simple u16 sum for arbitrary data. -/// WARNING: The data length should a multiple of 2. -fn sum(ptr: usize, size: usize, end: usize) -> u64 { - let mut res = 0u64; - - let mut p = ptr; - - for _ in 0..size / 2 { - // we could check the sizing once even before calling this function and omit this check, - // but it seems like verifier is not clever enough to deduct that it's valid - // TODO: Check if #[repr(packed)] would help - if p + 2 > end { - break; - } - - res += unsafe { *(p as *const u16) } as u64; - p += 2; - } - - res -} diff --git a/implementations/rust/ockam/ockam_ebpf/src/common.rs b/implementations/rust/ockam/ockam_ebpf/src/common.rs deleted file mode 100644 index 406be886b59..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/src/common.rs +++ /dev/null @@ -1,345 +0,0 @@ -use core::cmp::PartialEq; -use core::mem; - -use network_types::eth::{EthHdr, EtherType}; -use network_types::ip::{IpProto, Ipv4Hdr}; -use network_types::tcp::TcpHdr; - -use aya_ebpf::bindings::TC_ACT_PIPE; -use aya_ebpf::macros::map; -use aya_ebpf::maps::HashMap; -use aya_ebpf::programs::TcContext; - -use crate::conversion::{convert_ockam_to_tcp, convert_tcp_to_ockam}; -use crate::{error, trace, warn}; - -pub type Proto = u8; - -pub type Port = u16; - -// TODO: May want to switch to `HashMap::pinned` for efficiency (to share eBPFs) -// TODO: Split Inlet port map into inlet ingress and inlet egress maps for performance -// (and the same for outlets) - -/// Ports that we run inlets on -#[map] -static INLET_PORT_MAP: HashMap = HashMap::with_max_entries(1024, 0); - -/// Ports that we assigned for currently running connections -#[map] -static OUTLET_PORT_MAP: HashMap = HashMap::with_max_entries(1024, 0); - -#[derive(PartialEq)] -pub enum Direction { - Ingress, - Egress, -} - -#[inline(always)] -pub fn try_handle(ctx: &TcContext, direction: Direction) -> Result { - let ethhdr = match ptr_at::(ctx, 0) { - None => { - // Can it happen? - warn!(ctx, "SKIP non Ether"); - return Ok(TC_ACT_PIPE); - } - Some(ethhdr) => ethhdr, - }; - - if unsafe { (*ethhdr).ether_type } != EtherType::Ipv4 { - trace!(ctx, "SKIP non IPv4"); - return Ok(TC_ACT_PIPE); - } - - let ipv4hdr = match ptr_at::(ctx, EthHdr::LEN) { - None => { - // Should not happen - error!(ctx, "SKIP invalid IPv4 Header"); - return Ok(TC_ACT_PIPE); - } - Some(ipv4hdr) => ipv4hdr, - }; - let ipv4hdr_stack = unsafe { *ipv4hdr }; - - if direction == Direction::Ingress && ipv4hdr_stack.proto == IpProto::Tcp { - return handle_ingress_tcp_protocol(ctx, ipv4hdr); - } - - if direction == Direction::Egress && is_ockam_proto(ipv4hdr_stack.proto as Proto) { - return handle_egress_ockam_protocol(ctx, ipv4hdr); - } - - Ok(TC_ACT_PIPE) -} - -#[inline(always)] -fn is_ockam_proto(proto: Proto) -> bool { - // 146 to 252 are protocol values to be used for custom protocols on top of IPv4. - // Each ockam node with eBPF portals will generate a random value for itself to minimize risk - // of intersection with other nodes. Such intersection would not break anything, but decrease - // performance, as such nodes will receive a copy of packet dedicated for other nodes - // and discard them. - // The fact that protocol value is within this range doesn't guarantee that the packet is - // OCKAM protocol packet, but allows to early skip packets that are definitely not OCKAM - // protocol - proto >= 146 && proto <= 252 -} - -#[inline(always)] -fn handle_ingress_tcp_protocol(ctx: &TcContext, ipv4hdr: *mut Ipv4Hdr) -> Result { - let ipv4hdr_stack = unsafe { *ipv4hdr }; - let ipv4hdr_ihl = ipv4hdr_stack.ihl(); - - // IPv4 header length must be between 20 and 60 bytes. - if ipv4hdr_ihl < 5 || ipv4hdr_ihl > 15 { - error!(ctx, "SKIP invalid IPv4 Header length for TCP"); - return Ok(TC_ACT_PIPE); - } - let ipv4hdr_len = ipv4hdr_ihl as usize * 4; - - let src_ip = ipv4hdr_stack.src_addr(); - let dst_ip = ipv4hdr_stack.dst_addr(); - - let tcphdr = match ptr_at::(ctx, EthHdr::LEN + ipv4hdr_len) { - None => { - // Should not happen - // I haven't found if it's actually guaranteed, but the kernel code I found makes sure - // that tcp header is inside contiguous kmalloced piece of memory - error!(ctx, "SKIP invalid TCP Header for TCP"); - return Ok(TC_ACT_PIPE); - } - Some(tcphdr) => tcphdr, - }; - let tcphdr_stack = unsafe { *tcphdr }; - - let src_port = u16::from_be(tcphdr_stack.source); - let dst_port = u16::from_be(tcphdr_stack.dest); - - let syn = tcphdr_stack.syn(); - let ack = tcphdr_stack.ack(); - let fin = tcphdr_stack.fin(); - let rst = tcphdr_stack.rst(); - - if let Some(proto) = unsafe { INLET_PORT_MAP.get(&dst_port) } { - // Inlet logic - let proto = *proto; - trace!( - ctx, - "INLET. CONVERTING TCP PACKET TO {}. SRC: {}.{}.{}.{}:{}, DST: {}.{}.{}.{}:{}. SYN {} ACK {} FIN {} RST {}.", - proto, - src_ip.octets()[0], - src_ip.octets()[1], - src_ip.octets()[2], - src_ip.octets()[3], - src_port, - dst_ip.octets()[0], - dst_ip.octets()[1], - dst_ip.octets()[2], - dst_ip.octets()[3], - dst_port, - syn, - ack, - fin, - rst - ); - - convert_tcp_to_ockam(ctx, ipv4hdr, proto); - - return Ok(TC_ACT_PIPE); - } - - if let Some(proto) = unsafe { OUTLET_PORT_MAP.get(&dst_port) } { - // Outlet logic - let proto = *proto; - - trace!( - ctx, - "OUTLET. CONVERTING TCP PACKET TO {}. SRC: {}.{}.{}.{}:{}, DST: {}.{}.{}.{}:{}. SYN {} ACK {} FIN {} RST {}.", - proto, - src_ip.octets()[0], - src_ip.octets()[1], - src_ip.octets()[2], - src_ip.octets()[3], - src_port, - dst_ip.octets()[0], - dst_ip.octets()[1], - dst_ip.octets()[2], - dst_ip.octets()[3], - dst_port, - syn, - ack, - fin, - rst - ); - - convert_tcp_to_ockam(ctx, ipv4hdr, proto); - - return Ok(TC_ACT_PIPE); - } - - trace!( - ctx, - "SKIPPED TCP PACKET SRC: {}.{}.{}.{}:{}, DST: {}.{}.{}.{}:{}. SYN {} ACK {} FIN {} RST {}.", - src_ip.octets()[0], - src_ip.octets()[1], - src_ip.octets()[2], - src_ip.octets()[3], - src_port, - dst_ip.octets()[0], - dst_ip.octets()[1], - dst_ip.octets()[2], - dst_ip.octets()[3], - dst_port, - syn, - ack, - fin, - rst - ); - - Ok(TC_ACT_PIPE) -} - -#[inline(always)] -fn handle_egress_ockam_protocol(ctx: &TcContext, ipv4hdr: *mut Ipv4Hdr) -> Result { - let ipv4hdr_stack = unsafe { *ipv4hdr }; - let proto = ipv4hdr_stack.proto as u8; - let ipv4hdr_ihl = ipv4hdr_stack.ihl(); - if ipv4hdr_ihl < 5 || ipv4hdr_ihl > 15 { - error!(ctx, "SKIP invalid IPv4 Header length for OCKAM"); - return Ok(TC_ACT_PIPE); - } - let ipv4hdr_len = ipv4hdr_ihl as usize * 4; - - let src_ip = ipv4hdr_stack.src_addr(); - let dst_ip = ipv4hdr_stack.dst_addr(); - - if ptr_at::(ctx, EthHdr::LEN + ipv4hdr_len).is_none() { - if let Err(err) = ctx.pull_data((EthHdr::LEN + ipv4hdr_len + TcpHdr::LEN) as u32) { - error!( - ctx, - "Couldn't pull TCP header into contiguous memory. Err {}", err - ); - return Err(TC_ACT_PIPE); - } - }; - - let ipv4hdr = match ptr_at::(ctx, EthHdr::LEN) { - None => { - error!(ctx, "SKIP invalid IPv4 Header"); - return Ok(TC_ACT_PIPE); - } - Some(ipv4hdr) => ipv4hdr, - }; - - let tcphdr = match ptr_at::(ctx, EthHdr::LEN + ipv4hdr_len) { - Some(tcphdr) => tcphdr, - None => { - error!( - ctx, - "Couldn't get TCP header after pulling it into contiguous memory." - ); - return Err(TC_ACT_PIPE); - } - }; - let tcphdr_stack = unsafe { *tcphdr }; - - let src_port = u16::from_be(tcphdr_stack.source); - let dst_port = u16::from_be(tcphdr_stack.dest); - - let syn = tcphdr_stack.syn(); - let ack = tcphdr_stack.ack(); - let fin = tcphdr_stack.fin(); - let rst = tcphdr_stack.rst(); - - if let Some(port_proto) = unsafe { INLET_PORT_MAP.get(&src_port) } { - // Inlet logic - if proto == *port_proto { - trace!( - ctx, - "INLET. CONVERTING OCKAM {} packet to TCP. SRC: {}.{}.{}.{}:{}, DST: {}.{}.{}.{}:{}. SYN {} ACK {} FIN {} RST {}.", - proto, - src_ip.octets()[0], - src_ip.octets()[1], - src_ip.octets()[2], - src_ip.octets()[3], - src_port, - dst_ip.octets()[0], - dst_ip.octets()[1], - dst_ip.octets()[2], - dst_ip.octets()[3], - dst_port, - syn, - ack, - fin, - rst - ); - - convert_ockam_to_tcp(ctx, ipv4hdr, tcphdr); - - return Ok(TC_ACT_PIPE); - } - } - - if let Some(port_proto) = unsafe { OUTLET_PORT_MAP.get(&src_port) } { - // Outlet logic - if proto == *port_proto { - trace!( - ctx, - "OUTLET. CONVERTING OCKAM {} packet to TCP. SRC: {}.{}.{}.{}:{}, DST: {}.{}.{}.{}:{}. SYN {} ACK {} FIN {} RST {}.", - proto, - src_ip.octets()[0], - src_ip.octets()[1], - src_ip.octets()[2], - src_ip.octets()[3], - src_port, - dst_ip.octets()[0], - dst_ip.octets()[1], - dst_ip.octets()[2], - dst_ip.octets()[3], - dst_port, - syn, - ack, - fin, - rst - ); - - convert_ockam_to_tcp(ctx, ipv4hdr, tcphdr); - - return Ok(TC_ACT_PIPE); - } - } - - trace!( - ctx, - "SKIPPED OCKAM {} PACKET SRC: {}.{}.{}.{}:{}, DST: {}.{}.{}.{}:{}. SYN {} ACK {} FIN {} RST {}.", - proto, - src_ip.octets()[0], - src_ip.octets()[1], - src_ip.octets()[2], - src_ip.octets()[3], - src_port, - dst_ip.octets()[0], - dst_ip.octets()[1], - dst_ip.octets()[2], - dst_ip.octets()[3], - dst_port, - syn, - ack, - fin, - rst - ); - - Ok(TC_ACT_PIPE) -} - -#[inline(always)] -pub fn ptr_at(ctx: &TcContext, offset: usize) -> Option<*mut T> { - let start = ctx.data() + offset; - let end = ctx.data_end(); - - if start + mem::size_of::() > end { - return None; - } - - Some((start as *mut u8).cast::()) -} diff --git a/implementations/rust/ockam/ockam_ebpf/src/conversion.rs b/implementations/rust/ockam/ockam_ebpf/src/conversion.rs deleted file mode 100644 index 78bc1860857..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/src/conversion.rs +++ /dev/null @@ -1,24 +0,0 @@ -use crate::checksum::{iph_update_csum, tcph_update_csum}; -use crate::common::Proto; -use aya_ebpf::programs::TcContext; -use network_types::ip::{IpProto, Ipv4Hdr}; -use network_types::tcp::TcpHdr; - -#[inline(always)] -pub fn convert_tcp_to_ockam(ctx: &TcContext, ipv4hdr: *mut Ipv4Hdr, ockam_proto: Proto) { - unsafe { - (*ipv4hdr).proto = core::mem::transmute(ockam_proto); - } - - iph_update_csum(ctx, ipv4hdr); -} - -#[inline(always)] -pub fn convert_ockam_to_tcp(ctx: &TcContext, ipv4hdr: *mut Ipv4Hdr, tcphdr: *mut TcpHdr) { - unsafe { - (*ipv4hdr).proto = IpProto::Tcp; - } - - iph_update_csum(ctx, ipv4hdr); - tcph_update_csum(ipv4hdr, tcphdr); -} diff --git a/implementations/rust/ockam/ockam_ebpf/src/entrypoint.rs b/implementations/rust/ockam/ockam_ebpf/src/entrypoint.rs deleted file mode 100644 index 76bb12d74cb..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/src/entrypoint.rs +++ /dev/null @@ -1,62 +0,0 @@ -//! This crate contains the eBPF part of Ockam Reliable TCP Portals. -//! -//! ## Build -//! -//! ```bash -//! cargo build-ebpf -//! ``` -//! -//! Building eBPFs have roughly following requirements: -//! - Linux -//! - Rust nightly -//! - Some dependencies to be installed -//! -//! Because of that crate with the eBPF code is kept out of the workspace. -//! Example of a virtual machine to build it can be found in `ubuntu_x86.yaml`. -//! -//! Using ockam with eBPFs requires: -//! - Linux -//! - root (CAP_BPF, CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_ADMIN) -//! -//! Example of a virtual machine to run ockam with eBPF can be found in `ubuntu_arm.yaml`. -//! -//! eBPF is a small architecture-independent object file that is small enough, -//! to include it in the repo. -//! -//! The built eBPF object should be copied to `/implementations/rust/ockam/ockam_ebpf/ockam_ebpf`, -//! from where it will be grabbed by `ockam_transport_tcp` crate. - -#![no_std] -#![no_main] - -use aya_ebpf::macros::classifier; -use aya_ebpf::programs::TcContext; - -mod checksum; -mod checksum_helpers; -mod common; -mod conversion; - -#[cfg(feature = "logging")] -mod logger_aya; - -#[cfg(not(feature = "logging"))] -mod logger_noop; - -use crate::common::Direction; - -#[classifier] -pub fn ockam_ingress(ctx: TcContext) -> i32 { - common::try_handle(&ctx, Direction::Ingress).unwrap_or_else(|ret| ret) -} - -#[classifier] -pub fn ockam_egress(ctx: TcContext) -> i32 { - common::try_handle(&ctx, Direction::Egress).unwrap_or_else(|ret| ret) -} - -// TODO: Check if eBPF code can panic at all -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - unsafe { core::hint::unreachable_unchecked() } -} diff --git a/implementations/rust/ockam/ockam_ebpf/src/logger_aya.rs b/implementations/rust/ockam/ockam_ebpf/src/logger_aya.rs deleted file mode 100644 index 5cb22e02979..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/src/logger_aya.rs +++ /dev/null @@ -1,34 +0,0 @@ -#[macro_export] -macro_rules! error { - ($($x:expr),*) => { - aya_log_ebpf::error!{ $($x,)+ } - }; -} - -#[macro_export] -macro_rules! warn { - ($($x:expr),*) => { - aya_log_ebpf::warn!{ $($x,)+ } - } -} - -#[macro_export] -macro_rules! debug { - ($($x:expr),*) => { - aya_log_ebpf::debug!{ $($x,)+ } - } -} - -#[macro_export] -macro_rules! info { - ($($x:expr),*) => { - aya_log_ebpf::info!{ $($x,)+ } - } -} - -#[macro_export] -macro_rules! trace { - ($($x:expr),*) => { - aya_log_ebpf::trace!{ $($x,)+ } - } -} diff --git a/implementations/rust/ockam/ockam_ebpf/src/logger_noop.rs b/implementations/rust/ockam/ockam_ebpf/src/logger_noop.rs deleted file mode 100644 index cdb555ef113..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/src/logger_noop.rs +++ /dev/null @@ -1,44 +0,0 @@ -#[macro_export] -macro_rules! error { - ($($x:expr),*) => {{ - $( - _ = $x; - )* - }}; -} - -#[macro_export] -macro_rules! warn { - ($($x:expr),*) => {{ - $( - _ = $x; - )* - }}; -} - -#[macro_export] -macro_rules! debug { - ($($x:expr),*) => {{ - $( - _ = $x; - )* - }}; -} - -#[macro_export] -macro_rules! info { - ($($x:expr),*) => {{ - $( - _ = $x; - )* - }}; -} - -#[macro_export] -macro_rules! trace { - ($($x:expr),*) => {{ - $( - _ = $x; - )* - }}; -} diff --git a/implementations/rust/ockam/ockam_ebpf/ubuntu_arm.yaml b/implementations/rust/ockam/ockam_ebpf/ubuntu_arm.yaml deleted file mode 100644 index 8f7d9a6b723..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/ubuntu_arm.yaml +++ /dev/null @@ -1,56 +0,0 @@ -arch: "aarch64" - -images: - # Try to use release-yyyyMMdd image if available. Note that release-yyyyMMdd will be removed after several months. - - location: "https://cloud-images.ubuntu.com/releases/22.04/release-20230518/ubuntu-22.04-server-cloudimg-amd64.img" - arch: "x86_64" - digest: "sha256:afb820a9260217fd4c5c5aacfbca74aa7cd2418e830dc64ca2e0642b94aab161" - - location: "https://cloud-images.ubuntu.com/releases/22.04/release-20230518/ubuntu-22.04-server-cloudimg-arm64.img" - arch: "aarch64" - digest: "sha256:b47f8be40b5f91c37874817c3324a72cea1982a5fdad031d9b648c9623c3b4e2" - # Fallback to the latest release image. - - location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img" - arch: "x86_64" - - location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-arm64.img" - arch: "aarch64" - -memory: "12GiB" -cpus: 12 -disk: "48GiB" -ssh: - # You can choose any port or omit this. Specifying a value ensures same port bindings after restarts - # Forwarded to port 22 of the guest. - localPort: 4444 -# We are going to install all the necessary packages for our development environment. -# These include Python 3 and the bpfcc tools package. -provision: - - mode: system - script: | - #!/bin/bash - set -eux -o pipefail - export DEBIAN_FRONTEND=noninteractive - apt-get update - apt-get install --yes vim python3 python3-pip - apt-get install --yes apt-transport-https ca-certificates curl clang llvm jq - apt-get install --yes libelf-dev libpcap-dev libbfd-dev binutils-dev build-essential make - apt-get install --yes bsdutils - apt-get install --yes build-essential - apt-get install --yes pkgconf - apt-get install --yes zlib1g-dev libelf-dev - apt-get install --yes protobuf-compiler - apt-get install --yes libssl-dev - apt-get install --yes net-tools - - apt-get install --yes bpfcc-tools bpftrace - apt-get install --yes linux-tools-common linux-tools-generic - apt-get install --yes linux-headers-$(uname -r) linux-tools-$(uname -r) - - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - /root/.cargo/bin/rustup toolchain install nightly --component rust-src - /root/.cargo/bin/cargo install bpf-linker - - - mode: user - script: | - #!/bin/bash - set -eux -o pipefail - sudo cp /home/$(whoami).linux/.ssh/authorized_keys /root/.ssh/authorized_keys diff --git a/implementations/rust/ockam/ockam_ebpf/ubuntu_x86.yaml b/implementations/rust/ockam/ockam_ebpf/ubuntu_x86.yaml deleted file mode 100644 index 55abd8b01c4..00000000000 --- a/implementations/rust/ockam/ockam_ebpf/ubuntu_x86.yaml +++ /dev/null @@ -1,56 +0,0 @@ -arch: "x86_64" - -images: - # Try to use release-yyyyMMdd image if available. Note that release-yyyyMMdd will be removed after several months. - - location: "https://cloud-images.ubuntu.com/releases/22.04/release-20230518/ubuntu-22.04-server-cloudimg-amd64.img" - arch: "x86_64" - digest: "sha256:afb820a9260217fd4c5c5aacfbca74aa7cd2418e830dc64ca2e0642b94aab161" - - location: "https://cloud-images.ubuntu.com/releases/22.04/release-20230518/ubuntu-22.04-server-cloudimg-arm64.img" - arch: "aarch64" - digest: "sha256:b47f8be40b5f91c37874817c3324a72cea1982a5fdad031d9b648c9623c3b4e2" - # Fallback to the latest release image. - - location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img" - arch: "x86_64" - - location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-arm64.img" - arch: "aarch64" - -memory: "12GiB" -cpus: 12 -disk: "48GiB" -ssh: - # You can choose any port or omit this. Specifying a value ensures same port bindings after restarts - # Forwarded to port 22 of the guest. - localPort: 3333 -# We are going to install all the necessary packages for our development environment. -# These include Python 3 and the bpfcc tools package. -provision: - - mode: system - script: | - #!/bin/bash - set -eux -o pipefail - export DEBIAN_FRONTEND=noninteractive - apt-get update - apt-get install --yes vim python3 python3-pip - apt-get install --yes apt-transport-https ca-certificates curl clang llvm jq - apt-get install --yes libelf-dev libpcap-dev libbfd-dev binutils-dev build-essential make - apt-get install --yes bsdutils - apt-get install --yes build-essential - apt-get install --yes pkgconf - apt-get install --yes zlib1g-dev libelf-dev - apt-get install --yes protobuf-compiler - apt-get install --yes libssl-dev - apt-get install --yes net-tools - - apt-get install --yes bpfcc-tools bpftrace - apt-get install --yes linux-tools-common linux-tools-generic - apt-get install --yes linux-headers-$(uname -r) linux-tools-$(uname -r) - - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - /root/.cargo/bin/rustup toolchain install nightly --component rust-src - /root/.cargo/bin/cargo install bpf-linker - - - mode: user - script: | - #!/bin/bash - set -eux -o pipefail - sudo cp /home/$(whoami).linux/.ssh/authorized_keys /root/.ssh/authorized_keys diff --git a/implementations/rust/ockam/ockam_transport_tcp/Cargo.toml b/implementations/rust/ockam/ockam_transport_tcp/Cargo.toml index 914b8043501..57bf04fb2cf 100644 --- a/implementations/rust/ockam/ockam_transport_tcp/Cargo.toml +++ b/implementations/rust/ockam/ockam_transport_tcp/Cargo.toml @@ -29,7 +29,7 @@ no_std = ["ockam_macros/no_std", "ockam_transport_core/no_std"] alloc = ["minicbor/alloc"] aws-lc = ["tokio-rustls/aws-lc-rs"] ring = ["tokio-rustls/ring"] -privileged_portals = ["aya", "aya-log", "binary-layout", "caps", "nix"] +privileged_portals = ["ockam_ebpf", "aya", "aya-log", "binary-layout", "caps", "nix"] [build-dependencies] cfg_aliases = "0.2.1" @@ -40,6 +40,7 @@ cfg-if = "1.0.0" log = "0.4.21" minicbor = { version = "0.25.1", default-features = false, features = ["derive"] } ockam_core = { path = "../ockam_core", version = "^0.120.0" } +ockam_ebpf = { git = "https://github.com/build-trust/ockam-ebpf.git", version = "^0.1.0", optional = true } ockam_macros = { path = "../ockam_macros", version = "^0.35.0" } ockam_node = { path = "../ockam_node", version = "^0.132.0" } ockam_transport_core = { path = "../ockam_transport_core", version = "^0.97.0" } diff --git a/implementations/rust/ockam/ockam_transport_tcp/src/privileged_portal/ebpf_support.rs b/implementations/rust/ockam/ockam_transport_tcp/src/privileged_portal/ebpf_support.rs index 14f7337a025..171d1d97757 100644 --- a/implementations/rust/ockam/ockam_transport_tcp/src/privileged_portal/ebpf_support.rs +++ b/implementations/rust/ockam/ockam_transport_tcp/src/privileged_portal/ebpf_support.rs @@ -138,7 +138,7 @@ impl TcpTransportEbpfSupport { // like to specify the eBPF program at runtime rather than at compile-time, you can // reach for `Bpf::load_file` instead. - let ebpf_binary = aya::include_bytes_aligned!("../../../ockam_ebpf/ockam_ebpf"); + let ebpf_binary = ockam_ebpf::EBPF_BINARY; let mut ebpf = Ebpf::load(ebpf_binary).map_err(map_ebpf_error)?; // eBPF can be read from the filesystem in the runtime for development purposes // let ebpf_binary = std::fs::read(PATH).unwrap(); diff --git a/implementations/rust/ockam/xtask/CHANGELOG.md b/implementations/rust/ockam/xtask/CHANGELOG.md deleted file mode 100644 index f0e5ace9585..00000000000 --- a/implementations/rust/ockam/xtask/CHANGELOG.md +++ /dev/null @@ -1,10 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## v0.1.0 - 2024-08-21 -### Added - - - Initial implementation. diff --git a/implementations/rust/ockam/xtask/Cargo.toml b/implementations/rust/ockam/xtask/Cargo.toml deleted file mode 100644 index f783a829ca2..00000000000 --- a/implementations/rust/ockam/xtask/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "xtask" -version = "0.1.0" -authors = ["Ockam Developers"] -autoexamples = false -categories = [ - "network-programming", -] -edition = "2021" -homepage = "https://github.com/build-trust/ockam" -keywords = ["ockam", "crypto", "network", "networking", "tcp"] -license = "Apache-2.0" -publish = false -readme = "README.md" -repository = "https://github.com/build-trust/ockam/implementations/rust/ockam/xtask" -rust-version = "1.70.0" -description = """ -xtask to build eBPF object file. -""" - -[dependencies] -clap = { version = "4.1", features = ["derive"] } diff --git a/implementations/rust/ockam/xtask/README.md b/implementations/rust/ockam/xtask/README.md deleted file mode 100644 index f2fccfac354..00000000000 --- a/implementations/rust/ockam/xtask/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# xtask - -[![crate][crate-image]][crate-link] -[![docs][docs-image]][docs-link] -[![license][license-image]][license-link] -[![discuss][discuss-image]][discuss-link] - -Ockam is a library for building devices that communicate securely, privately -and trustfully with cloud services and other devices. - -This xtask is designed for targets that require custom scripts to be built. -Currently, its only purpose is to build `ockam_ebpf` eBPF object file. - -### Build - -```bash -cargo build-ebpf -``` - -Building eBPFs have roughly following requirements: - - Linux - - Rust nightly - - Some dependencies to be installed - -Because of that crate with the eBPF code is kept out of the workspace. -Example of a virtual machine to build it can be found in `ubuntu_x86.yaml`. - -Using ockam with eBPFs requires: - - Linux - - root (CAP_BPF, CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_ADMIN) - -Example of a virtual machine to run ockam with eBPF can be found in `ubuntu_arm.yaml`. - -eBPF is a small architecture-independent object file that is small enough, -to include it in the repo. - -The built eBPF object should be copied to `/implementations/rust/ockam/ockam_ebpf/ockam_ebpf`, -from where it will be grabbed by `ockam_transport_tcp` crate. - -## Usage - -Add this to your `Cargo.toml`: - -``` -[dependencies] -xtask = "0.1.0" -``` - -## License - -This code is licensed under the terms of the [Apache License 2.0][license-link]. - -[main-ockam-crate-link]: https://crates.io/crates/ockam - -[crate-image]: https://img.shields.io/crates/v/xtask.svg -[crate-link]: https://crates.io/crates/xtask - -[docs-image]: https://docs.rs/xtask/badge.svg -[docs-link]: https://docs.rs/xtask - -[license-image]: https://img.shields.io/badge/License-Apache%202.0-green.svg -[license-link]: https://github.com/build-trust/ockam/blob/HEAD/LICENSE - -[discuss-image]: https://img.shields.io/badge/Discuss-Github%20Discussions-ff70b4.svg -[discuss-link]: https://github.com/build-trust/ockam/discussions diff --git a/implementations/rust/ockam/xtask/src/main.rs b/implementations/rust/ockam/xtask/src/main.rs deleted file mode 100644 index 429ba588890..00000000000 --- a/implementations/rust/ockam/xtask/src/main.rs +++ /dev/null @@ -1,112 +0,0 @@ -//! This xtask is designed for targets that require custom scripts to be built. -//! Currently, its only purpose is to build `ockam_ebpf` eBPF object file. -//! -//! ## Build -//! -//! ```bash -//! cargo build-ebpf -//! ``` -//! -//! Building eBPFs have roughly following requirements: -//! - Linux -//! - Rust nightly -//! - Some dependencies to be installed -//! -//! Because of that crate with the eBPF code is kept out of the workspace. -//! Example of a virtual machine to build it can be found in `ubuntu_x86.yaml`. -//! -//! Using ockam with eBPFs requires: -//! - Linux -//! - root (CAP_BPF, CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_ADMIN) -//! -//! Example of a virtual machine to run ockam with eBPF can be found in `ubuntu_arm.yaml`. -//! -//! eBPF is a small architecture-independent object file that is small enough, -//! to include it in the repo. -//! -//! The built eBPF object should be copied to `/implementations/rust/ockam/ockam_ebpf/ockam_ebpf`, -//! from where it will be grabbed by `ockam_transport_tcp` crate. - -use std::{path::PathBuf, process::Command}; - -use clap::Parser; - -#[derive(Debug, Copy, Clone)] -pub enum Architecture { - BpfEl, - // eBPF code may need to be updated to behave correctly on big-endian (especially checksum calc) - // BpfEb, -} - -impl std::str::FromStr for Architecture { - type Err = String; - - fn from_str(s: &str) -> Result { - Ok(match s { - "bpfel-unknown-none" => Architecture::BpfEl, - // "bpfeb-unknown-none" => Architecture::BpfEb, - _ => return Err("invalid target".to_owned()), - }) - } -} - -impl std::fmt::Display for Architecture { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - Architecture::BpfEl => "bpfel-unknown-none", - // Architecture::BpfEb => "bpfeb-unknown-none", - }) - } -} - -#[derive(Debug, Parser, Clone)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - target: Architecture, - #[clap(long, short, group = "profile_group")] - release: bool, - #[clap(long, group = "profile_group")] - profile: Option, - #[clap(long)] - target_dir: Option, -} - -pub fn build_ebpf(opts: Options, dir: PathBuf) { - let target = format!("--target={}", opts.target); - let mut args = vec!["build", target.as_str(), "-Z", "build-std=core"]; - if opts.release { - args.push("--release") - } - - if let Some(profile) = &opts.profile { - args.push("--profile"); - args.push(profile); - } - - if let Some(target_dir) = &opts.target_dir { - args.push("--target-dir"); - args.push(target_dir.to_str().unwrap()); - } - - // Command::new creates a child process which inherits all env variables. This means env - // vars set by the cargo xtask command are also inherited. RUSTUP_TOOLCHAIN is removed - // so the rust-toolchain.toml file in the -ebpf folder is honored. - - let status = Command::new("cargo") - .current_dir(dir.clone()) - .env_remove("RUSTUP_TOOLCHAIN") - .args(&args) - .status() - .expect("failed to run build bpf program"); - - assert!(status.success(), "failed to build bpf program"); -} - -fn main() { - let opts = Options::parse(); - - let dir = PathBuf::from("implementations/rust/ockam/ockam_ebpf"); - - build_ebpf(opts.clone(), dir.clone()); -}