commit ad6e426abc25930e68ba257c0ed9745cb9c6fd2c Author: Ishan Jain Date: Sat Jan 18 12:33:36 2025 +0530 added initial version with ringbuffers and queues diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ad80a02 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +### https://raw.github.com/github/gitignore/master/Rust.gitignore + +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +**/*.mmdb diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..ca4e86f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,876 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + +[[package]] +name = "aya" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d18bc4e506fbb85ab7392ed993a7db4d1a452c71b75a246af4a80ab8c9d2dd50" +dependencies = [ + "assert_matches", + "aya-obj", + "bitflags", + "bytes", + "libc", + "log", + "object", + "once_cell", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "aya-build" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "765c92c523541cbf5e3a94c7a6ff4068a4d9537f98a2eeb136461c0537ded8c1" +dependencies = [ + "anyhow", + "cargo_metadata", +] + +[[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" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b600d806c1d07d3b81ab5f4a2a95fd80f479a0d3f1d68f29064d660865f85f02" +dependencies = [ + "aya", + "aya-log-common", + "bytes", + "log", + "thiserror 1.0.69", + "tokio", +] + +[[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 = "aya-obj" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51b96c5a8ed8705b40d655273bc4212cbbf38d4e3be2788f36306f154523ec7" +dependencies = [ + "bytes", + "core-error", + "hashbrown", + "log", + "object", + "thiserror 1.0.69", +] + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.11", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.5.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_derive" +version = "4.5.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "core-error" +version = "0.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efcdb2972eb64230b4c50646d8498ff73f5128d196a90c7236eec4cbe8619b8f" +dependencies = [ + "version_check", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +dependencies = [ + "env_filter", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + +[[package]] +name = "geofw" +version = "0.1.0" +dependencies = [ + "anyhow", + "aya", + "aya-build", + "aya-log", + "clap", + "env_logger", + "geofw-common", + "geofw-ebpf", + "libc", + "log", + "maxminddb", + "mio", + "tokio", +] + +[[package]] +name = "geofw-common" +version = "0.1.0" +dependencies = [ + "aya", +] + +[[package]] +name = "geofw-ebpf" +version = "0.1.0" +dependencies = [ + "aya-ebpf", + "aya-log-ebpf", + "geofw-common", + "network-types", + "which", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnetwork" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" +dependencies = [ + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "log" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + +[[package]] +name = "maxminddb" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6087e5d8ea14861bb7c7f573afbc7be3798d3ef0fae87ec4fd9a4de9a127c3c" +dependencies = [ + "ipnetwork", + "log", + "memchr", + "serde", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.52.0", +] + +[[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 = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "crc32fast", + "hashbrown", + "indexmap", + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[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.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.135" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "syn" +version = "2.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl 2.0.11", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio" +version = "1.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +dependencies = [ + "backtrace", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "which" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +dependencies = [ + "either", + "home", + "rustix", + "winsafe", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..70d9e7b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,26 @@ +[workspace] +resolver = "2" +members = ["geofw", "geofw-common", "geofw-ebpf"] +default-members = ["geofw", "geofw-common"] + +[workspace.dependencies] +aya = { version = "0.13.1", default-features = false } +aya-build = { version = "0.1.2", default-features = false } +aya-ebpf = { version = "0.1.1", default-features = false } +aya-log = { version = "0.2.1", default-features = false } +aya-log-ebpf = { version = "0.1.1", default-features = false } + +anyhow = { version = "1", default-features = false } +# `std` feature is currently required to build `clap`. +# +# See https://github.com/clap-rs/clap/blob/61f5ee5/clap_builder/src/lib.rs#L15. +clap = { version = "4.5.20", default-features = false, features = ["std"] } +env_logger = { version = "0.11.5", default-features = false } +libc = { version = "0.2.159", default-features = false } +log = { version = "0.4.22", default-features = false } +tokio = { version = "1.40.0", default-features = false } +which = { version = "6.0.0", default-features = false } + +[profile.release.package.geofw-ebpf] +debug = 2 +codegen-units = 1 diff --git a/README.md b/README.md new file mode 100644 index 0000000..cb49f22 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# geofw + +## Prerequisites + +1. stable rust toolchains: `rustup toolchain install stable` +1. nightly rust toolchains: `rustup toolchain install nightly --component rust-src` +1. (if cross-compiling) rustup target: `rustup target add ${ARCH}-unknown-linux-musl` +1. (if cross-compiling) LLVM: (e.g.) `brew install llvm` (on macOS) +1. (if cross-compiling) C toolchain: (e.g.) [`brew install filosottile/musl-cross/musl-cross`](https://github.com/FiloSottile/homebrew-musl-cross) (on macOS) +1. bpf-linker: `cargo install bpf-linker` (`--no-default-features` on macOS) + +## Build & Run + +Use `cargo build`, `cargo check`, etc. as normal. Run your program with: + +```shell +cargo run --release --config 'target."cfg(all())".runner="sudo -E"' +``` + +Cargo build scripts are used to automatically build the eBPF correctly and include it in the +program. + +## Cross-compiling on macOS + +Cross compilation should work on both Intel and Apple Silicon Macs. + +```shell +CC=${ARCH}-linux-musl-gcc cargo build --package geofw --release \ + --target=${ARCH}-unknown-linux-musl \ + --config=target.${ARCH}-unknown-linux-musl.linker=\"${ARCH}-linux-musl-gcc\" +``` +The cross-compiled program `target/${ARCH}-unknown-linux-musl/release/geofw` can be +copied to a Linux server or VM and run there. diff --git a/geofw-common/Cargo.toml b/geofw-common/Cargo.toml new file mode 100644 index 0000000..701982c --- /dev/null +++ b/geofw-common/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "geofw-common" +version = "0.1.0" +edition = "2021" + +[features] +default = [] +user = ["aya"] + +[dependencies] +aya = { workspace = true, optional = true } + +[lib] +path = "src/lib.rs" diff --git a/geofw-common/src/lib.rs b/geofw-common/src/lib.rs new file mode 100644 index 0000000..0c9ac1a --- /dev/null +++ b/geofw-common/src/lib.rs @@ -0,0 +1 @@ +#![no_std] diff --git a/geofw-ebpf/Cargo.toml b/geofw-ebpf/Cargo.toml new file mode 100644 index 0000000..2043a89 --- /dev/null +++ b/geofw-ebpf/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "geofw-ebpf" +version = "0.1.0" +edition = "2021" + +[dependencies] +geofw-common = { path = "../geofw-common" } + +aya-ebpf = { workspace = true } +aya-log-ebpf = { workspace = true } +network-types = "0.0.7" + +[build-dependencies] +which = { workspace = true } + +[[bin]] +name = "geofw" +path = "src/main.rs" diff --git a/geofw-ebpf/build.rs b/geofw-ebpf/build.rs new file mode 100644 index 0000000..f83c317 --- /dev/null +++ b/geofw-ebpf/build.rs @@ -0,0 +1,17 @@ +use which::which; + +/// Building this crate has an undeclared dependency on the `bpf-linker` binary. This would be +/// better expressed by [artifact-dependencies][bindeps] but issues such as +/// https://github.com/rust-lang/cargo/issues/12385 make their use impractical for the time being. +/// +/// This file implements an imperfect solution: it causes cargo to rebuild the crate whenever the +/// mtime of `which bpf-linker` changes. Note that possibility that a new bpf-linker is added to +/// $PATH ahead of the one used as the cache key still exists. Solving this in the general case +/// would require rebuild-if-changed-env=PATH *and* rebuild-if-changed={every-directory-in-PATH} +/// which would likely mean far too much cache invalidation. +/// +/// [bindeps]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html?highlight=feature#artifact-dependencies +fn main() { + let bpf_linker = which("bpf-linker").unwrap(); + println!("cargo:rerun-if-changed={}", bpf_linker.to_str().unwrap()); +} diff --git a/geofw-ebpf/src/lib.rs b/geofw-ebpf/src/lib.rs new file mode 100644 index 0000000..3ac3e59 --- /dev/null +++ b/geofw-ebpf/src/lib.rs @@ -0,0 +1,3 @@ +#![no_std] + +// This file exists to enable the library target. diff --git a/geofw-ebpf/src/main.rs b/geofw-ebpf/src/main.rs new file mode 100644 index 0000000..a70a288 --- /dev/null +++ b/geofw-ebpf/src/main.rs @@ -0,0 +1,119 @@ +#![no_std] +#![no_main] + +use aya_ebpf::{ + bindings::xdp_action, + macros::{map, xdp}, + maps::{Queue, RingBuf}, + programs::XdpContext, +}; +use aya_log_ebpf::info; +use core::{ + mem, + net::{Ipv4Addr, Ipv6Addr}, +}; +use network_types::{ + eth::{EthHdr, EtherType}, + ip::{Ipv4Hdr, Ipv6Hdr}, +}; + +#[xdp] +pub fn geofw(ctx: XdpContext) -> u32 { + match try_geofw(ctx) { + Ok(ret) => ret, + Err(_) => xdp_action::XDP_ABORTED, + } +} + +#[inline(always)] +fn ptr_at(ctx: &XdpContext, offset: usize) -> Option<*const T> { + let start = ctx.data(); + let end = ctx.data_end(); + let len = mem::size_of::(); + + if start + offset + len > end { + return None; + } + + Some((start + offset) as *const T) +} + +#[map] +static REQUEST: RingBuf = RingBuf::with_byte_size(128, 0); + +#[map] +static RESPONSE: Queue = Queue::with_max_entries(128, 0); + +fn try_geofw(ctx: XdpContext) -> Result { + let eth: *const EthHdr = ptr_at(&ctx, 0).ok_or(xdp_action::XDP_PASS)?; + + match unsafe { (*eth).ether_type } { + EtherType::Ipv4 => filter_ip_packet(ctx), + EtherType::Ipv6 => filter_ipv6_packet(ctx), + + _ => Ok(xdp_action::XDP_PASS), + } +} + +fn filter_ip_packet(ctx: XdpContext) -> Result { + let ip: *const Ipv4Hdr = ptr_at(&ctx, EthHdr::LEN).ok_or(xdp_action::XDP_PASS)?; + let source = unsafe { (*ip).src_addr() }; + + if let Some(mut buf) = REQUEST.reserve::(0) { + buf.write(source); + buf.submit(0); + } + + let mut result = false; + let mut n = 0; + while n < 10 { + if let Some(r) = RESPONSE.pop() { + result = r; + break; + } + n += 1; + } + + if result { + Ok(xdp_action::XDP_PASS) + } else { + info!(&ctx, "ipv4 source = {} result = {}", source, result as u8); + + Ok(xdp_action::XDP_DROP) + } +} + +fn filter_ipv6_packet(ctx: XdpContext) -> Result { + let ip: *const Ipv6Hdr = ptr_at(&ctx, EthHdr::LEN).ok_or(xdp_action::XDP_PASS)?; + let source = unsafe { (*ip).src_addr() }; + + // info!(&ctx, "ipv6 source = {}", source); + if let Some(mut buf) = REQUEST.reserve::(0) { + buf.write(source); + buf.submit(0); + } + + let mut result = false; + let mut n = 0; + while n < 10 { + if let Some(r) = RESPONSE.pop() { + result = r; + break; + } + n += 1; + } + + if result { + Ok(xdp_action::XDP_PASS) + } else { + info!(&ctx, "ipv4 source = {} result = {}", source, result as u8); + + Ok(xdp_action::XDP_DROP) + } +} + +#[cfg(not(test))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/geofw/Cargo.toml b/geofw/Cargo.toml new file mode 100644 index 0000000..729cb03 --- /dev/null +++ b/geofw/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "geofw" +version = "0.1.0" +edition = "2021" + +[dependencies] +geofw-common = { path = "../geofw-common", features = ["user"] } + +anyhow = { workspace = true, default-features = true } +aya = { workspace = true } +aya-log = { workspace = true } +env_logger = { workspace = true } +libc = { workspace = true } +log = { workspace = true } +tokio = { workspace = true, features = ["macros", "rt", "rt-multi-thread", "net", "signal"] } + +clap = { workspace = true, features = ["derive"] } +mio = "1.0.3" +maxminddb = "0.24.0" +[build-dependencies] +anyhow = { workspace = true } +aya-build = { workspace = true } +# TODO(https://github.com/rust-lang/cargo/issues/12375): this should be an artifact dependency, but +# it's not possible to tell cargo to use `-Z build-std` to build it. We cargo-in-cargo in the build +# script to build this, but we want to teach cargo about the dependecy so that cache invalidation +# works properly. +# +# Note also that https://github.com/rust-lang/cargo/issues/10593 occurs when `target = ...` is added +# to an artifact dependency; it seems possible to work around that by setting `resolver = "1"` in +# Cargo.toml in the workspace root. +# +# Finally note that *any* usage of `artifact = ...` in *any* Cargo.toml in the workspace breaks +# workflows with stable cargo; stable cargo outright refuses to load manifests that use unstable +# features. +geofw-ebpf = { path = "../geofw-ebpf" } + +[[bin]] +name = "geofw" +path = "src/main.rs" diff --git a/geofw/build.rs b/geofw/build.rs new file mode 100644 index 0000000..6aee473 --- /dev/null +++ b/geofw/build.rs @@ -0,0 +1,14 @@ +use anyhow::{anyhow, Context as _}; +use aya_build::cargo_metadata; + +fn main() -> anyhow::Result<()> { + let cargo_metadata::Metadata { packages, .. } = cargo_metadata::MetadataCommand::new() + .no_deps() + .exec() + .context("MetadataCommand::exec")?; + let ebpf_package = packages + .into_iter() + .find(|cargo_metadata::Package { name, .. }| name == "geofw-ebpf") + .ok_or_else(|| anyhow!("geofw-ebpf package not found"))?; + aya_build::build_ebpf([ebpf_package]) +} diff --git a/geofw/src/main.rs b/geofw/src/main.rs new file mode 100644 index 0000000..65cbf02 --- /dev/null +++ b/geofw/src/main.rs @@ -0,0 +1,107 @@ +use anyhow::Context as _; +use aya::{ + maps::{Queue, RingBuf}, + programs::{Xdp, XdpFlags}, +}; +use clap::Parser; +use log::{debug, warn}; +use maxminddb::geoip2; +use std::{ + fs::File, + io::Write, + net::{IpAddr, Ipv4Addr, Ipv6Addr}, + os::{fd::AsRawFd, unix::io::FromRawFd}, +}; +use tokio::signal; + +#[derive(Debug, Parser)] +struct Opt { + #[clap(short, long, default_value = "enp6s18")] + iface: String, +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let opt = Opt::parse(); + + env_logger::init(); + + // Bump the memlock rlimit. This is needed for older kernels that don't use the + // new memcg based accounting, see https://lwn.net/Articles/837122/ + let rlim = libc::rlimit { + rlim_cur: libc::RLIM_INFINITY, + rlim_max: libc::RLIM_INFINITY, + }; + let ret = unsafe { libc::setrlimit(libc::RLIMIT_MEMLOCK, &rlim) }; + if ret != 0 { + debug!("remove limit on locked memory failed, ret is: {}", ret); + } + + // This will include your eBPF object file as raw bytes at compile-time and load it at + // runtime. This approach is recommended for most real-world use cases. If you would + // like to specify the eBPF program at runtime rather than at compile-time, you can + // reach for `Bpf::load_file` instead. + let mut ebpf = aya::Ebpf::load(aya::include_bytes_aligned!(concat!( + env!("OUT_DIR"), + "/geofw" + )))?; + if let Err(e) = aya_log::EbpfLogger::init(&mut ebpf) { + // This can happen if you remove all log statements from your eBPF program. + warn!("failed to initialize eBPF logger: {}", e); + } + let Opt { iface } = opt; + let program: &mut Xdp = ebpf.program_mut("geofw").unwrap().try_into()?; + program.load()?; + program.attach(&iface, XdpFlags::default()) + .context("failed to attach the XDP program with default flags - try changing XdpFlags::default() to XdpFlags::SKB_MODE")?; + + // TODO(ishan) + // Download geolite2 db + // Keep it updated, once every 24h + // Read from request ring buffer in a loop + // do lookup and write responses to the response buffer + + std::thread::spawn(move || { + let mut request = RingBuf::try_from(ebpf.take_map("REQUEST").unwrap()).unwrap(); + let mut response = Queue::try_from(ebpf.take_map("RESPONSE").unwrap()).unwrap(); + + let db_reader = maxminddb::Reader::open_readfile("./geofw/GeoLite2-City.mmdb") + .expect("error in opening geolite2 db"); + + loop { + while let Some(msg) = request.next() { + let msg = &*msg; + let addr = match msg.len() { + 4 => IpAddr::V4(Ipv4Addr::from([msg[0], msg[1], msg[2], msg[3]])), + 16 => IpAddr::V6(Ipv6Addr::from([ + msg[0], msg[1], msg[2], msg[3], msg[4], msg[5], msg[6], msg[7], msg[8], + msg[9], msg[10], msg[11], msg[12], msg[13], msg[14], msg[15], + ])), + + _ => unreachable!(), + }; + + let result = db_reader + .lookup(addr) + .map(|x: geoip2::City| { + x.country + .map(|country| country.iso_code.map(|x| x != "IN").unwrap_or(true)) + .unwrap_or(true) + }) + .unwrap_or(true); + + response + .push(result as u8, 0) + .expect("error in writing result to queue"); + println!("wrote {} for {:?}", result, addr); + } + } + }); + + let ctrl_c = signal::ctrl_c(); + println!("Waiting for Ctrl-C..."); + ctrl_c.await?; + println!("Exiting..."); + + Ok(()) +} diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..eaf29a5 --- /dev/null +++ b/run.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e +set -o pipefail + +RUST_LOG=info cargo run --config 'target."cfg(all())".runner="sudo -E"' diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..f53e9c8 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,5 @@ +group_imports = "StdExternalCrate" +imports_granularity = "Crate" +reorder_imports = true +unstable_features = true +edition = "2018"