diff --git a/Cargo.lock b/Cargo.lock index af65f93..aba7eaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,9 +226,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.52" +version = "1.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3" +checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583" dependencies = [ "find-msvc-tools", "shlex", @@ -248,9 +248,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" dependencies = [ "iana-time-zone", "js-sys", @@ -261,9 +261,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.54" +version = "4.5.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" +checksum = "a75ca66430e33a14957acc24c5077b503e7d374151b2b4b3a10c83b4ceb4be0e" dependencies = [ "clap_builder", "clap_derive", @@ -271,9 +271,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.54" +version = "4.5.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" +checksum = "793207c7fa6300a0608d1080b858e5fdbe713cdc1c8db9fb17777d8a13e63df0" dependencies = [ "anstream", "anstyle", @@ -283,9 +283,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ "heck", "proc-macro2", @@ -295,9 +295,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" [[package]] name = "colorchoice" @@ -632,9 +632,9 @@ dependencies = [ [[package]] name = "euclid" -version = "0.22.11" +version = "0.22.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +checksum = "df61bf483e837f88d5c2291dcf55c67be7e676b3a51acc48db3a7b163b91ed63" dependencies = [ "num-traits", ] @@ -662,9 +662,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41" +checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" [[package]] name = "finl_unicode" @@ -714,9 +714,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", @@ -771,9 +771,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -837,15 +837,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.14.0" @@ -887,9 +878,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.83" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" dependencies = [ "once_cell", "wasm-bindgen", @@ -912,7 +903,7 @@ checksum = "8fe90c1150662e858c7d5f945089b7517b0a80d8bf7ba4b1b5ffc984e7230a5b" dependencies = [ "hashbrown 0.16.1", "portable-atomic", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1059,10 +1050,7 @@ dependencies = [ [[package]] name = "network-types" version = "0.1.0" -source = "git+https://github.com/vadorovsky/network-types?rev=b78424c#b78424c582951ac0af4392bce595d0cb236280e8" -dependencies = [ - "memoffset", -] +source = "git+https://github.com/vadorovsky/network-types?rev=c6f9c28#c6f9c28442cfde2bd3e3fda21a32402349edcc0c" [[package]] name = "nix" @@ -1089,9 +1077,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] name = "num-derive" @@ -1183,7 +1171,7 @@ dependencies = [ "crossterm", "dirs", "env_logger", - "itertools 0.14.0", + "itertools", "kanal", "libc", "log", @@ -1343,18 +1331,18 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro2" -version = "1.0.105" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -1404,11 +1392,11 @@ dependencies = [ "compact_str", "hashbrown 0.16.1", "indoc", - "itertools 0.14.0", + "itertools", "kasuari", "lru", "strum", - "thiserror 2.0.17", + "thiserror 2.0.18", "unicode-segmentation", "unicode-truncate", "unicode-width", @@ -1456,7 +1444,7 @@ dependencies = [ "hashbrown 0.16.1", "indoc", "instability", - "itertools 0.14.0", + "itertools", "line-clipping", "ratatui-core", "strum", @@ -1480,9 +1468,9 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1659,9 +1647,9 @@ dependencies = [ [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "smallvec" @@ -1798,11 +1786,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -1818,9 +1806,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -1829,24 +1817,24 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "9da98b7d9b7dad93488a84b8248efc35352b0b2657397d4167e7ad67e5d535e5" dependencies = [ "deranged", "libc", "num-conv", "num_threads", "powerfmt", - "serde", + "serde_core", "time-core", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "tui-big-text" @@ -1856,7 +1844,7 @@ checksum = "0cb3cf7714229ca4503c1b94050bce7ae4f5bbcf9e5b3d24bee858f15ef23cef" dependencies = [ "derive_builder", "font8x8", - "itertools 0.14.0", + "itertools", "ratatui-core", ] @@ -1896,11 +1884,11 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-truncate" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fbf03860ff438702f3910ca5f28f8dac63c1c11e7efb5012b8b175493606330" +checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" dependencies = [ - "itertools 0.13.0", + "itertools", "unicode-segmentation", "unicode-width", ] @@ -1919,9 +1907,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" dependencies = [ "atomic", "getrandom 0.3.4", @@ -1953,18 +1941,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" dependencies = [ "cfg-if", "once_cell", @@ -1975,9 +1963,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1985,9 +1973,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ "bumpalo", "proc-macro2", @@ -1998,9 +1986,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" dependencies = [ "unicode-ident", ] @@ -2169,9 +2157,9 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] name = "xtask" @@ -2183,6 +2171,6 @@ dependencies = [ [[package]] name = "zmij" -version = "1.0.12" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc5a66a20078bf1251bde995aa2fdcc4b800c70b5d92dd2c62abc5c60f679f8" +checksum = "02aae0f83f69aafc94776e879363e9771d7ecbffe2c7fbb6c14c5e00dfe88439" diff --git a/Cargo.toml b/Cargo.toml index 65f4584..f934f3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ repository = "https://github.com/pythops/oryx" homepage = "https://github.com/pythops/oryx" [workspace.dependencies] -network-types = { git = "https://github.com/vadorovsky/network-types", rev = "b78424c" } +network-types = { git = "https://github.com/vadorovsky/network-types", rev = "c6f9c28" } [profile.release] opt-level = 3 diff --git a/oryx-common/src/lib.rs b/oryx-common/src/lib.rs index 2c36e08..5e30482 100644 --- a/oryx-common/src/lib.rs +++ b/oryx-common/src/lib.rs @@ -4,7 +4,14 @@ use core::mem; use network_types::{ - arp::ArpHdr, eth::EthHdr, icmp::Icmp, ip::IpHdr, sctp::SctpHdr, tcp::TcpHdr, udp::UdpHdr, + arp::ArpHdr, + eth::EthHdr, + icmp::Icmp, + igmp::{IGMPv1Hdr, IGMPv2Hdr, IGMPv3MembershipQueryHdr, IGMPv3MembershipReportHdr}, + ip::IpHdr, + sctp::SctpHdr, + tcp::TcpHdr, + udp::UdpHdr, }; pub mod protocols; @@ -65,4 +72,20 @@ pub enum ProtoHdr { Udp(UdpHdr), Sctp(SctpHdr), Icmp(Icmp), + Igmp(IgmpHdr), +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub enum IgmpHdr { + V1(IGMPv1Hdr), + V2(IGMPv2Hdr), + V3(IGMPv3Hdr), +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub enum IGMPv3Hdr { + Query(IGMPv3MembershipQueryHdr), + Report(IGMPv3MembershipReportHdr), } diff --git a/oryx-common/src/protocols.rs b/oryx-common/src/protocols.rs index c89b8ec..6c680e5 100644 --- a/oryx-common/src/protocols.rs +++ b/oryx-common/src/protocols.rs @@ -40,7 +40,7 @@ impl TransportProtocol { // Network Protocols -pub const NB_NETWORK_PROTOCOL: u16 = 4; +pub const NB_NETWORK_PROTOCOL: u16 = 5; #[derive(Debug, Copy, Clone, PartialEq, AsRefStr, Display, EnumString)] #[repr(C)] @@ -56,15 +56,19 @@ pub enum NetworkProtocol { #[strum(ascii_case_insensitive)] Icmpv6 = 3, + + #[strum(ascii_case_insensitive)] + Igmp = 4, } impl NetworkProtocol { - pub fn all() -> [NetworkProtocol; 4] { + pub fn all() -> [NetworkProtocol; 5] { [ NetworkProtocol::Ipv4, NetworkProtocol::Ipv6, NetworkProtocol::Icmpv4, NetworkProtocol::Icmpv6, + NetworkProtocol::Igmp, ] } } diff --git a/oryx-ebpf/Cargo.lock b/oryx-ebpf/Cargo.lock index 710477b..a49707e 100644 --- a/oryx-ebpf/Cargo.lock +++ b/oryx-ebpf/Cargo.lock @@ -8,12 +8,6 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - [[package]] name = "aya-build" version = "0.1.3" @@ -69,9 +63,9 @@ dependencies = [ [[package]] name = "branches" -version = "0.3.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11502672c5570f77f6bdf573332483f8475bab6a7fda00f1fae8ddb5a6245c0" +checksum = "e426eb5cc1900033930ec955317b302e68f19f326cc7bb0c8a86865a826cdf0c" dependencies = [ "rustc_version", ] @@ -127,22 +121,10 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "network-types" version = "0.1.0" -source = "git+https://github.com/vadorovsky/network-types?rev=b78424c#b78424c582951ac0af4392bce595d0cb236280e8" -dependencies = [ - "memoffset", -] +source = "git+https://github.com/vadorovsky/network-types?rev=c6f9c28#c6f9c28442cfde2bd3e3fda21a32402349edcc0c" [[package]] name = "oryx-common" @@ -164,9 +146,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.105" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -185,9 +167,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -294,18 +276,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -326,6 +308,6 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "zmij" -version = "1.0.12" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc5a66a20078bf1251bde995aa2fdcc4b800c70b5d92dd2c62abc5c60f679f8" +checksum = "02aae0f83f69aafc94776e879363e9771d7ecbffe2c7fbb6c14c5e00dfe88439" diff --git a/oryx-ebpf/Cargo.toml b/oryx-ebpf/Cargo.toml index d016506..1dc211e 100644 --- a/oryx-ebpf/Cargo.toml +++ b/oryx-ebpf/Cargo.toml @@ -10,8 +10,8 @@ homepage = "https://github.com/pythops/oryx" [dependencies] aya-ebpf = "0.1.1" oryx-common = { path = "../oryx-common" } -network-types = { git = "https://github.com/vadorovsky/network-types", rev = "b78424c" } -branches = { version = "0.3", default-features = false } +network-types = { git = "https://github.com/vadorovsky/network-types", rev = "c6f9c28" } +branches = { version = "0.4", default-features = false } [[bin]] name = "oryx" diff --git a/oryx-ebpf/src/main.rs b/oryx-ebpf/src/main.rs index 55cf662..25e1a2f 100644 --- a/oryx-ebpf/src/main.rs +++ b/oryx-ebpf/src/main.rs @@ -14,13 +14,14 @@ use network_types::{ arp::ArpHdr, eth::{EthHdr, EtherType}, icmp::{Icmp, IcmpHdr, IcmpV6Hdr}, + igmp::{IGMPv1Hdr, IGMPv2Hdr, IGMPv3MembershipQueryHdr, IGMPv3MembershipReportHdr}, ip::{IpHdr, IpProto, Ipv4Hdr, Ipv6Hdr}, sctp::SctpHdr, tcp::TcpHdr, udp::UdpHdr, }; use oryx_common::{ - MAX_FIREWALL_RULES, MAX_RULES_PORT, ProtoHdr, RawData, RawFrame, RawPacket, + IGMPv3Hdr, IgmpHdr, MAX_FIREWALL_RULES, MAX_RULES_PORT, ProtoHdr, RawData, RawFrame, RawPacket, protocols::{LinkProtocol, NetworkProtocol, Protocol, TransportProtocol}, }; @@ -304,6 +305,140 @@ fn process(ctx: TcContext) -> Result { }); } } + + IpProto::Igmp => { + if filter_packet(Protocol::Network(NetworkProtocol::Igmp)) { + return Ok(TC_ACT_PIPE); + } + + let payload_length = unsafe { + u16::from_be_bytes((*ipv4_header).tot_len) - (*ipv4_header).ihl() as u16 + }; + + let ihl: u8 = ctx.load(EthHdr::LEN).map_err(|_| ())?; + let ihl = (ihl & 0x0F) * 4; + + let igmp_type: u8 = ctx.load(EthHdr::LEN + ihl as usize).map_err(|_| ())?; + + match igmp_type { + 0x11 => { + if payload_length == 8 { + // v1 or v2 + let max_response_time: u8 = + ctx.load(EthHdr::LEN + ihl as usize + 1).map_err(|_| ())?; + + if max_response_time == 0 { + //v1 + let igmp_header: *const IGMPv1Hdr = + ptr_at(&ctx, EthHdr::LEN + ihl as usize)?; + + unsafe { + submit(RawData { + frame: RawFrame { + header: *eth_header, + payload: RawPacket::Ip( + IpHdr::V4(*ipv4_header), + ProtoHdr::Igmp(IgmpHdr::V1(*igmp_header)), + ), + }, + pid, + }); + } + } else { + // v2 + let igmp_header: *const IGMPv2Hdr = + ptr_at(&ctx, EthHdr::LEN + ihl as usize)?; + + unsafe { + submit(RawData { + frame: RawFrame { + header: *eth_header, + payload: RawPacket::Ip( + IpHdr::V4(*ipv4_header), + ProtoHdr::Igmp(IgmpHdr::V2(*igmp_header)), + ), + }, + pid, + }); + } + } + } else { + // v3 + let igmp_header: *const IGMPv3MembershipQueryHdr = + ptr_at(&ctx, EthHdr::LEN + ihl as usize)?; + + unsafe { + submit(RawData { + frame: RawFrame { + header: *eth_header, + payload: RawPacket::Ip( + IpHdr::V4(*ipv4_header), + ProtoHdr::Igmp(IgmpHdr::V3(IGMPv3Hdr::Query( + *igmp_header, + ))), + ), + }, + pid, + }); + } + } + } + 0x12 => { + let igmp_header: *const IGMPv1Hdr = + ptr_at(&ctx, EthHdr::LEN + ihl as usize)?; + + unsafe { + submit(RawData { + frame: RawFrame { + header: *eth_header, + payload: RawPacket::Ip( + IpHdr::V4(*ipv4_header), + ProtoHdr::Igmp(IgmpHdr::V1(*igmp_header)), + ), + }, + pid, + }); + } + } + 0x16 | 0x17 => { + let igmp_header: *const IGMPv2Hdr = + ptr_at(&ctx, EthHdr::LEN + ihl as usize)?; + + unsafe { + submit(RawData { + frame: RawFrame { + header: *eth_header, + payload: RawPacket::Ip( + IpHdr::V4(*ipv4_header), + ProtoHdr::Igmp(IgmpHdr::V2(*igmp_header)), + ), + }, + pid, + }); + } + } + 0x22 => { + let igmp_header: *const IGMPv3MembershipReportHdr = + ptr_at(&ctx, EthHdr::LEN + ihl as usize)?; + + unsafe { + submit(RawData { + frame: RawFrame { + header: *eth_header, + payload: RawPacket::Ip( + IpHdr::V4(*ipv4_header), + ProtoHdr::Igmp(IgmpHdr::V3(IGMPv3Hdr::Report( + *igmp_header, + ))), + ), + }, + pid, + }); + } + } + _ => {} + } + } _ => {} } } diff --git a/oryx-tui/src/cli.rs b/oryx-tui/src/cli.rs index 9da3c61..eee80bc 100644 --- a/oryx-tui/src/cli.rs +++ b/oryx-tui/src/cli.rs @@ -54,7 +54,7 @@ pub fn cli() -> Command { .value_delimiter(',') .num_args(1..) .default_value("all") - .value_parser(["ipv4", "ipv6", "icmp", "all"]), + .value_parser(["ipv4", "ipv6", "icmpv4", "icmpv6", "igmp", "all"]), ) .arg( arg!(--link ) diff --git a/oryx-tui/src/export.rs b/oryx-tui/src/export.rs index be0f77b..da28770 100644 --- a/oryx-tui/src/export.rs +++ b/oryx-tui/src/export.rs @@ -136,6 +136,13 @@ pub fn export(packets: &PacketStore) -> Result<()> { ipv4_packet.src_ip, "-", ipv4_packet.dst_ip, "-", "ICMPv4", pid, date )?; } + IpProto::Igmp(_) => { + writeln!( + file, + "{:39} {:^11} {:39} {:^11} {:10} {:10} {:10}", + ipv4_packet.src_ip, "-", ipv4_packet.dst_ip, "-", "IGMP", pid, date + )?; + } }, IpPacket::V6(ipv6_packet) => match ipv6_packet.proto { IpProto::Tcp(p) => { @@ -184,6 +191,10 @@ pub fn export(packets: &PacketStore) -> Result<()> { ipv6_packet.src_ip, "-", ipv6_packet.dst_ip, "-", "ICMPv6", pid, date )?; } + IpProto::Igmp(_) => { + //IGMP is for IPv4 only + unreachable!() + } }, }, } diff --git a/oryx-tui/src/filter/network.rs b/oryx-tui/src/filter/network.rs index 9cffdfa..c547c97 100644 --- a/oryx-tui/src/filter/network.rs +++ b/oryx-tui/src/filter/network.rs @@ -150,6 +150,16 @@ impl NetworkFilter { }, "ICMPv6", ]), + Row::new(vec![ + { + if self.selected_protocols.contains(&NetworkProtocol::Igmp) { + " " + } else { + "" + } + }, + "IGMP", + ]), ]; let network_filters_table = Table::new(network_filters, widths) diff --git a/oryx-tui/src/packet.rs b/oryx-tui/src/packet.rs index d684f80..e2534e6 100644 --- a/oryx-tui/src/packet.rs +++ b/oryx-tui/src/packet.rs @@ -11,12 +11,18 @@ use direction::TrafficDirection; use link::{ArpPacket, ArpType, MacAddr}; use network::{IpPacket, icmp::IcmpPacket, icmp::icmpv4, icmp::icmpv6, ip::IpProto}; use network_types::{eth::EthHdr, icmp::Icmp, ip::IpHdr}; -use oryx_common::{ProtoHdr, RawFrame, RawPacket}; +use oryx_common::{IGMPv3Hdr, IgmpHdr, ProtoHdr, RawFrame, RawPacket}; use transport::{SctpPacket, TcpPacket, UdpPacket}; use crate::packet::network::{ - icmp::icmpv4::Icmpv4Packet, icmp::icmpv6::Icmpv6Packet, ip::ipv4::Ipv4Packet, - ip::ipv6::Ipv6Packet, + icmp::{icmpv4::Icmpv4Packet, icmpv6::Icmpv6Packet}, + igmp::{ + IgmpPacket, IgmpType, + igmpv1::IGMPv1Packet, + igmpv2::IGMPv2Packet, + igmpv3::{IGMPv3MembershipQueryPacket, IGMPv3MembershipReportPacket, IGMPv3Packet}, + }, + ip::{ipv4::Ipv4Packet, ipv6::Ipv6Packet}, }; #[derive(Debug, Copy, Clone)] @@ -98,6 +104,46 @@ impl From for EthFrame { checksum: u16::from_be_bytes(icmp_header.check), })) } + ProtoHdr::Igmp(igmp_header) => match igmp_header { + IgmpHdr::V1(igmpv1_hdr) => { + let igmp_type = + IgmpType::try_from(igmpv1_hdr.type_() | 1 << 1).unwrap(); + IpProto::Igmp(IgmpPacket::V1(IGMPv1Packet { + igmp_type, + checksum: igmpv1_hdr.checksum(), + group_address: Ipv4Addr::from_bits(igmpv1_hdr.group_address()), + })) + } + IgmpHdr::V2(igmpv2_hdr) => { + let igmp_type = + IgmpType::try_from(igmpv2_hdr.message_type).unwrap(); + IpProto::Igmp(IgmpPacket::V2(IGMPv2Packet { + igmp_type, + max_response_time: igmpv2_hdr.max_response_time, + checksum: igmpv2_hdr.checksum(), + group_address: Ipv4Addr::from_bits(igmpv2_hdr.group_address()), + })) + } + IgmpHdr::V3(igmpv3_hdr) => match igmpv3_hdr { + IGMPv3Hdr::Query(query) => IpProto::Igmp(IgmpPacket::V3( + IGMPv3Packet::Query(IGMPv3MembershipQueryPacket { + max_response_code: query.max_response_time, + checksum: query.checksum(), + group_address: Ipv4Addr::from_bits(query.group_address()), + s: query.s(), + qrv: query.qrv(), + qqic: query.qqic, + nb_source_addr: query.nb_sources() as u16, + }), + )), + IGMPv3Hdr::Report(report) => IpProto::Igmp(IgmpPacket::V3( + IGMPv3Packet::Report(IGMPv3MembershipReportPacket { + checksum: report.checksum(), + nb_group_records: report.nb_group_records(), + }), + )), + }, + }, _ => unreachable!(), }; diff --git a/oryx-tui/src/packet/network.rs b/oryx-tui/src/packet/network.rs index 9fe1d3c..15a6e18 100644 --- a/oryx-tui/src/packet/network.rs +++ b/oryx-tui/src/packet/network.rs @@ -1,4 +1,5 @@ pub mod icmp; +pub mod igmp; pub mod ip; use core::fmt::Display; @@ -78,6 +79,20 @@ impl IpPacket { ip_packet.render(network_block, frame); icmp_packet.render(transport_block, frame); } + IpProto::Igmp(igmp_packet) => { + let (transport_block, network_block) = { + let chunks = Layout::default() + .direction(Direction::Vertical) + .constraints([Constraint::Length(7), Constraint::Length(13)]) + .flex(ratatui::layout::Flex::SpaceAround) + .margin(2) + .split(block); + + (chunks[0], chunks[1]) + }; + ip_packet.render(network_block, frame); + igmp_packet.render(transport_block, frame); + } _ => unreachable!(), }, IpPacket::V6(ip_packet) => match ip_packet.proto { @@ -181,6 +196,9 @@ impl Display for IpPacket { IpProto::Icmp(_) => { write!(f, "{} {} ICMP", ipv4_packet.src_ip, ipv4_packet.dst_ip) } + IpProto::Igmp(_) => { + write!(f, "{} {} IGMP", ipv4_packet.src_ip, ipv4_packet.dst_ip) + } }, IpPacket::V6(ipv6_packet) => match ipv6_packet.proto { IpProto::Tcp(tcp_packet) => { @@ -216,6 +234,9 @@ impl Display for IpPacket { IpProto::Icmp(_) => { write!(f, "{} {} ICMP", ipv6_packet.src_ip, ipv6_packet.dst_ip) } + IpProto::Igmp(_) => { + unreachable!() + } }, } } diff --git a/oryx-tui/src/packet/network/igmp.rs b/oryx-tui/src/packet/network/igmp.rs new file mode 100644 index 0000000..4408077 --- /dev/null +++ b/oryx-tui/src/packet/network/igmp.rs @@ -0,0 +1,79 @@ +pub mod igmpv1; +pub mod igmpv2; +pub mod igmpv3; + +use std::fmt::Display; + +use ratatui::{Frame, layout::Rect}; + +use crate::packet::network::igmp::{ + igmpv1::IGMPv1Packet, igmpv2::IGMPv2Packet, igmpv3::IGMPv3Packet, +}; + +#[derive(Debug, Copy, Clone)] +pub enum IgmpPacket { + V1(IGMPv1Packet), + V2(IGMPv2Packet), + V3(IGMPv3Packet), +} + +impl IgmpPacket { + pub fn render(self, block: Rect, frame: &mut Frame) { + match self { + IgmpPacket::V1(packet) => { + packet.render(block, frame); + } + IgmpPacket::V2(packet) => { + packet.render(block, frame); + } + IgmpPacket::V3(packet) => { + packet.render(block, frame); + } + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum IgmpType { + MembershipQuery = 0x11, + IGMPv1MembershipReport = 0x12, + IGMPv2MembershipReport = 0x16, + IGMPv3MembershipReport = 0x22, + LeaveGroup = 0x17, +} + +impl TryFrom for IgmpType { + type Error = &'static str; + fn try_from(value: u8) -> Result { + match value { + 0x11 => Ok(IgmpType::MembershipQuery), + 0x12 => Ok(IgmpType::IGMPv1MembershipReport), + 0x16 => Ok(IgmpType::IGMPv2MembershipReport), + 0x22 => Ok(IgmpType::IGMPv3MembershipReport), + 0x17 => Ok(IgmpType::LeaveGroup), + _ => Err("Unknown igmp type"), + } + } +} + +impl Display for IgmpType { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + IgmpType::MembershipQuery => { + write!(f, "Membership Query") + } + IgmpType::IGMPv1MembershipReport => { + write!(f, "IGMPv1 Membership Report") + } + IgmpType::IGMPv2MembershipReport => { + write!(f, "IGMPv2 Membership Report") + } + IgmpType::IGMPv3MembershipReport => { + write!(f, "IGMPv3 Membership Report") + } + IgmpType::LeaveGroup => { + write!(f, "Leave Group") + } + } + } +} diff --git a/oryx-tui/src/packet/network/igmp/igmpv1.rs b/oryx-tui/src/packet/network/igmp/igmpv1.rs new file mode 100644 index 0000000..15415d7 --- /dev/null +++ b/oryx-tui/src/packet/network/igmp/igmpv1.rs @@ -0,0 +1,73 @@ +use ratatui::{ + Frame, + layout::{Constraint, Direction, Layout, Rect}, + style::{Style, Stylize}, + text::Span, + widgets::{Block, Borders, Padding, Paragraph, Row, Table}, +}; +use std::net::Ipv4Addr; + +use crate::packet::network::igmp::IgmpType; + +#[derive(Debug, Copy, Clone)] +pub struct IGMPv1Packet { + pub igmp_type: IgmpType, + pub checksum: u16, + pub group_address: Ipv4Addr, +} + +impl IGMPv1Packet { + pub fn render(self, block: Rect, frame: &mut Frame) { + let (title_block, data_block) = { + let chunks = Layout::default() + .direction(Direction::Horizontal) + .constraints([Constraint::Length(10), Constraint::Fill(1)]) + .margin(2) + .split(block); + + (chunks[0], chunks[1]) + }; + let title = Paragraph::new("IGMPv1") + .bold() + .block(Block::new().padding(Padding::top({ + if title_block.height.is_multiple_of(2) { + (title_block.height / 2).saturating_sub(1) + } else { + title_block.height / 2 + } + }))); + + let widths = [Constraint::Length(23), Constraint::Fill(1)]; + let infos = [ + Row::new(vec![ + Span::styled("Type", Style::new().bold()), + Span::from(self.igmp_type.to_string()), + ]), + Row::new(vec![ + Span::styled("Checksum", Style::new().bold()), + Span::from(format!("{:#0x}", self.checksum)), + ]), + Row::new(vec![ + Span::styled("Group Address", Style::new().bold()), + Span::from({ + if self.igmp_type == IgmpType::IGMPv1MembershipReport { + self.group_address.to_string() + } else { + "-".to_string() + } + }), + ]), + ]; + + let table = Table::new(infos, widths).column_spacing(2).block( + Block::default() + .borders(Borders::LEFT) + .border_style(Style::new().bold().yellow()) + .border_type(ratatui::widgets::BorderType::Thick) + .style(Style::default()), + ); + + frame.render_widget(table, data_block); + frame.render_widget(title, title_block); + } +} diff --git a/oryx-tui/src/packet/network/igmp/igmpv2.rs b/oryx-tui/src/packet/network/igmp/igmpv2.rs new file mode 100644 index 0000000..759c7dc --- /dev/null +++ b/oryx-tui/src/packet/network/igmp/igmpv2.rs @@ -0,0 +1,72 @@ +use ratatui::{ + Frame, + layout::{Constraint, Direction, Layout, Rect}, + style::{Style, Stylize}, + text::Span, + widgets::{Block, Borders, Padding, Paragraph, Row, Table}, +}; +use std::net::Ipv4Addr; + +use crate::packet::network::igmp::IgmpType; + +#[derive(Debug, Copy, Clone)] +pub struct IGMPv2Packet { + pub igmp_type: IgmpType, + pub max_response_time: u8, + pub checksum: u16, + pub group_address: Ipv4Addr, +} + +impl IGMPv2Packet { + pub fn render(self, block: Rect, frame: &mut Frame) { + let (title_block, data_block) = { + let chunks = Layout::default() + .direction(Direction::Horizontal) + .constraints([Constraint::Length(10), Constraint::Fill(1)]) + .margin(2) + .split(block); + + (chunks[0], chunks[1]) + }; + let title = Paragraph::new("IGMPv2") + .bold() + .block(Block::new().padding(Padding::top({ + if title_block.height.is_multiple_of(2) { + (title_block.height / 2).saturating_sub(1) + } else { + title_block.height / 2 + } + }))); + + let widths = [Constraint::Length(23), Constraint::Fill(1)]; + let infos = [ + Row::new(vec![ + Span::styled("Type", Style::new().bold()), + Span::from(self.igmp_type.to_string()), + ]), + Row::new(vec![ + Span::styled("Max Response time", Style::new().bold()), + Span::from(self.max_response_time.to_string()), + ]), + Row::new(vec![ + Span::styled("Checksum", Style::new().bold()), + Span::from(format!("{:#0x}", self.checksum)), + ]), + Row::new(vec![ + Span::styled("Group Address", Style::new().bold()), + Span::from(self.group_address.to_string()), + ]), + ]; + + let table = Table::new(infos, widths).column_spacing(2).block( + Block::default() + .borders(Borders::LEFT) + .border_style(Style::new().bold().yellow()) + .border_type(ratatui::widgets::BorderType::Thick) + .style(Style::default()), + ); + + frame.render_widget(table, data_block); + frame.render_widget(title, title_block); + } +} diff --git a/oryx-tui/src/packet/network/igmp/igmpv3.rs b/oryx-tui/src/packet/network/igmp/igmpv3.rs new file mode 100644 index 0000000..f798059 --- /dev/null +++ b/oryx-tui/src/packet/network/igmp/igmpv3.rs @@ -0,0 +1,164 @@ +use ratatui::{ + Frame, + layout::{Constraint, Direction, Layout, Rect}, + style::{Style, Stylize}, + text::Span, + widgets::{Block, Borders, Padding, Paragraph, Row, Table}, +}; +use std::net::Ipv4Addr; + +#[derive(Debug, Copy, Clone)] +pub enum IGMPv3Packet { + Report(IGMPv3MembershipReportPacket), + Query(IGMPv3MembershipQueryPacket), +} + +impl IGMPv3Packet { + pub fn render(self, block: Rect, frame: &mut Frame) { + match self { + IGMPv3Packet::Report(packet) => { + packet.render(block, frame); + } + IGMPv3Packet::Query(packet) => { + packet.render(block, frame); + } + } + } +} + +#[derive(Debug, Copy, Clone)] +pub struct IGMPv3MembershipReportPacket { + pub checksum: u16, + pub nb_group_records: u16, +} + +#[derive(Debug, Copy, Clone)] +pub struct IGMPv3MembershipQueryPacket { + pub max_response_code: u8, + pub checksum: u16, + pub group_address: Ipv4Addr, + pub s: u8, + pub qrv: u8, + pub qqic: u8, + pub nb_source_addr: u16, +} + +impl IGMPv3MembershipQueryPacket { + pub fn render(self, block: Rect, frame: &mut Frame) { + let (title_block, data_block) = { + let chunks = Layout::default() + .direction(Direction::Horizontal) + .constraints([Constraint::Length(10), Constraint::Fill(1)]) + .margin(2) + .split(block); + + (chunks[0], chunks[1]) + }; + let title = Paragraph::new("IGMPv3") + .bold() + .block(Block::new().padding(Padding::top({ + if title_block.height.is_multiple_of(2) { + (title_block.height / 2).saturating_sub(1) + } else { + title_block.height / 2 + } + }))); + + let widths = [Constraint::Length(23), Constraint::Fill(1)]; + let infos = [ + Row::new(vec![ + Span::styled("Type", Style::new().bold()), + Span::from("IGMPv3 Membership Query"), + ]), + Row::new(vec![ + Span::styled("Max Response time", Style::new().bold()), + Span::from(self.max_response_code.to_string()), + ]), + Row::new(vec![ + Span::styled("Checksum", Style::new().bold()), + Span::from(format!("{:#0x}", self.checksum)), + ]), + Row::new(vec![ + Span::styled("Group Address", Style::new().bold()), + Span::from(self.group_address.to_string()), + ]), + Row::new(vec![ + Span::styled("S", Style::new().bold()), + Span::from(self.s.to_string()), + ]), + Row::new(vec![ + Span::styled("QRV", Style::new().bold()), + Span::from(self.qrv.to_string()), + ]), + Row::new(vec![ + Span::styled("QQIC", Style::new().bold()), + Span::from(self.qqic.to_string()), + ]), + Row::new(vec![ + Span::styled("Number of Sources", Style::new().bold()), + Span::from(self.nb_source_addr.to_string()), + ]), + ]; + + let table = Table::new(infos, widths).column_spacing(2).block( + Block::default() + .borders(Borders::LEFT) + .border_style(Style::new().bold().yellow()) + .border_type(ratatui::widgets::BorderType::Thick) + .style(Style::default()), + ); + + frame.render_widget(table, data_block); + frame.render_widget(title, title_block); + } +} + +impl IGMPv3MembershipReportPacket { + pub fn render(self, block: Rect, frame: &mut Frame) { + let (title_block, data_block) = { + let chunks = Layout::default() + .direction(Direction::Horizontal) + .constraints([Constraint::Length(10), Constraint::Fill(1)]) + .margin(2) + .split(block); + + (chunks[0], chunks[1]) + }; + let title = Paragraph::new("IGMPv3") + .bold() + .block(Block::new().padding(Padding::top({ + if title_block.height.is_multiple_of(2) { + (title_block.height / 2).saturating_sub(1) + } else { + title_block.height / 2 + } + }))); + + let widths = [Constraint::Length(23), Constraint::Fill(1)]; + let infos = [ + Row::new(vec![ + Span::styled("Type", Style::new().bold()), + Span::from("IGMPv3 Membership Report"), + ]), + Row::new(vec![ + Span::styled("Checksum", Style::new().bold()), + Span::from(format!("{:#0x}", self.checksum)), + ]), + Row::new(vec![ + Span::styled("Number Group Records", Style::new().bold()), + Span::from(self.nb_group_records.to_string()), + ]), + ]; + + let table = Table::new(infos, widths).column_spacing(2).block( + Block::default() + .borders(Borders::LEFT) + .border_style(Style::new().bold().yellow()) + .border_type(ratatui::widgets::BorderType::Thick) + .style(Style::default()), + ); + + frame.render_widget(table, data_block); + frame.render_widget(title, title_block); + } +} diff --git a/oryx-tui/src/packet/network/ip.rs b/oryx-tui/src/packet/network/ip.rs index ee2306c..0183159 100644 --- a/oryx-tui/src/packet/network/ip.rs +++ b/oryx-tui/src/packet/network/ip.rs @@ -2,7 +2,7 @@ pub mod ipv4; pub mod ipv6; use crate::packet::{ - network::icmp::IcmpPacket, + network::{icmp::IcmpPacket, igmp::IgmpPacket}, transport::{SctpPacket, TcpPacket, UdpPacket}, }; @@ -12,4 +12,5 @@ pub enum IpProto { Udp(UdpPacket), Sctp(SctpPacket), Icmp(IcmpPacket), + Igmp(IgmpPacket), } diff --git a/oryx-tui/src/packet/network/ip/ipv4.rs b/oryx-tui/src/packet/network/ip/ipv4.rs index d280cb5..5aabb67 100644 --- a/oryx-tui/src/packet/network/ip/ipv4.rs +++ b/oryx-tui/src/packet/network/ip/ipv4.rs @@ -58,7 +58,7 @@ impl Ipv4Packet { ]), Row::new(vec![ Span::styled("Internet Header Length", Style::new().bold()), - Span::from(format!("{} bytes", self.ihl * 4)), + Span::from(format!("{} bytes", self.ihl)), ]), Row::new(vec![ Span::styled("Type Of Service", Style::new().bold()), diff --git a/oryx-tui/src/section/alert/threat/synflood.rs b/oryx-tui/src/section/alert/threat/synflood.rs index b0812e4..12edf61 100644 --- a/oryx-tui/src/section/alert/threat/synflood.rs +++ b/oryx-tui/src/section/alert/threat/synflood.rs @@ -24,7 +24,7 @@ impl ratatui::widgets::WidgetRef for SynFlood { fn render_ref(&self, area: Rect, buf: &mut Buffer) { let mut ips: Vec<(IpAddr, usize)> = { self.map.clone().into_iter().collect() }; - ips.sort_by(|a, b| b.1.cmp(&a.1)); + ips.sort_by_key(|b| std::cmp::Reverse(b.1)); ips.retain(|(_, count)| *count > 10_000); diff --git a/oryx-tui/src/section/inspection.rs b/oryx-tui/src/section/inspection.rs index 8929e92..c642d28 100644 --- a/oryx-tui/src/section/inspection.rs +++ b/oryx-tui/src/section/inspection.rs @@ -395,6 +395,16 @@ impl Inspection { fuzzy::highlight(pattern, "ICMPv4".to_string()).cyan(), pid, ]), + IpProto::Igmp(_) => Row::new(vec![ + fuzzy::highlight(pattern, ipv4_packet.src_ip.to_string()) + .blue(), + Cell::from(Line::from("-").centered()).yellow(), + fuzzy::highlight(pattern, ipv4_packet.dst_ip.to_string()) + .blue(), + Cell::from(Line::from("-").centered()).yellow(), + fuzzy::highlight(pattern, "IGMP".to_string()).cyan(), + pid, + ]), }, IpPacket::V6(ipv6_packet) => match ipv6_packet.proto { IpProto::Tcp(p) => Row::new(vec![ @@ -437,6 +447,10 @@ impl Inspection { fuzzy::highlight(pattern, "ICMPv6".to_string()).cyan(), pid, ]), + IpProto::Igmp(_) => { + // IGMP is for Ipv4 only + unreachable!() + } }, }, } @@ -525,6 +539,18 @@ impl Inspection { Span::from("ICMPv4".to_string()).into_centered_line().cyan(), pid, ]), + IpProto::Igmp(_) => Row::new(vec![ + Span::from(ipv4_packet.src_ip.to_string()) + .into_centered_line() + .blue(), + Span::from("-").into_centered_line().yellow(), + Span::from(ipv4_packet.dst_ip.to_string()) + .into_centered_line() + .blue(), + Span::from("-").into_centered_line().yellow(), + Span::from("IGMP".to_string()).into_centered_line().cyan(), + pid, + ]), }, IpPacket::V6(ipv6_packet) => match ipv6_packet.proto { IpProto::Tcp(p) => Row::new(vec![ @@ -587,6 +613,10 @@ impl Inspection { Span::from("ICMPv6".to_string()).into_centered_line().cyan(), pid, ]), + IpProto::Igmp(_) => { + // IGMP is for IPv4 only + unreachable!() + } }, }, } diff --git a/oryx-tui/src/section/stats.rs b/oryx-tui/src/section/stats.rs index 6b3f3ea..5ee8cc7 100644 --- a/oryx-tui/src/section/stats.rs +++ b/oryx-tui/src/section/stats.rs @@ -100,6 +100,9 @@ impl Stats { IpProto::Icmp(_) => { packet_stats.network.icmpv4 += 1; } + IpProto::Igmp(_) => { + packet_stats.network.igmp += 1; + } } } IpPacket::V6(ipv6_packet) => { @@ -139,6 +142,10 @@ impl Stats { IpProto::Icmp(_) => { packet_stats.network.icmpv6 += 1; } + IpProto::Igmp(_) => { + // IGMP is for IPv4 only + unreachable!() + } } } }, @@ -161,7 +168,7 @@ impl Stats { addresses: HashMap, usize)>, ) -> Vec<(IpAddr, (Option, usize))> { let mut items: Vec<(IpAddr, (Option, usize))> = addresses.into_iter().collect(); - items.sort_by(|a, b| b.1.1.cmp(&a.1.1)); + items.sort_by_key(|b| std::cmp::Reverse(b.1.1)); items.into_iter().take(10).collect() } @@ -182,7 +189,7 @@ impl Stats { [ Constraint::Max(60), Constraint::Length(12), - Constraint::Length(38), + Constraint::Length(44), Constraint::Length(10), ] .as_ref(), @@ -203,16 +210,24 @@ impl Stats { .label("ARP") .style(Style::new().fg(Color::LightYellow)) .value_style(Style::new().fg(Color::Black).bg(Color::LightYellow)) - .text_value(if packet_stats.total != 0 { - format!("{}%", packet_stats.link.arp * 100 / packet_stats.total) - } else { - "0%".to_string() - }) - .value(if packet_stats.total != 0 { - (packet_stats.link.arp * 100 / packet_stats.total) as u64 - } else { - 0 - })]), + .text_value( + if let Some(val) = + (packet_stats.link.arp * 100).checked_div(packet_stats.total) + { + format!("{val}%") + } else { + "0%".to_string() + }, + ) + .value( + if let Some(val) = + (packet_stats.link.arp * 100).checked_div(packet_stats.total) + { + val as u64 + } else { + 0 + }, + )]), ) .block(Block::new().padding(Padding::horizontal(1))) .max(100); @@ -226,81 +241,134 @@ impl Stats { .label("TCP") .style(Style::new().fg(Color::LightBlue)) .value_style(Style::new().fg(Color::Black).bg(Color::LightBlue)) - .text_value(if packet_stats.total != 0 { - format!("{}%", packet_stats.transport.tcp * 100 / packet_stats.total) - } else { - "0%".to_string() - }) - .value(if packet_stats.total != 0 { - (packet_stats.transport.tcp * 100 / packet_stats.total) as u64 - } else { - 0 - }), + .text_value( + if let Some(val) = + (packet_stats.transport.tcp * 100).checked_div(packet_stats.total) + { + format!("{val}%") + } else { + "0%".to_string() + }, + ) + .value( + if let Some(val) = + (packet_stats.transport.tcp * 100).checked_div(packet_stats.total) + { + val as u64 + } else { + 0 + }, + ), Bar::default() .label("UDP") .style(Style::new().fg(Color::LightGreen)) .value_style(Style::new().fg(Color::Black).bg(Color::LightGreen)) - .text_value(if packet_stats.total != 0 { - format!("{}%", packet_stats.transport.udp * 100 / packet_stats.total) - } else { - "0%".to_string() - }) - .value(if packet_stats.total != 0 { - (packet_stats.transport.udp * 100 / packet_stats.total) as u64 - } else { - 0 - }), + .text_value( + if let Some(val) = + (packet_stats.transport.udp * 100).checked_div(packet_stats.total) + { + format!("{val}%") + } else { + "0%".to_string() + }, + ) + .value( + if let Some(val) = + (packet_stats.transport.udp * 100).checked_div(packet_stats.total) + { + val as u64 + } else { + 0 + }, + ), Bar::default() .label("SCTP") .style(Style::new().fg(Color::LightRed)) .value_style(Style::new().fg(Color::Black).bg(Color::LightRed)) - .text_value(if packet_stats.total != 0 { - format!( - "{}%", - packet_stats.transport.sctp * 100 / packet_stats.total - ) - } else { - "0%".to_string() - }) - .value(if packet_stats.total != 0 { - (packet_stats.transport.sctp * 100 / packet_stats.total) as u64 - } else { - 0 - }), + .text_value( + if let Some(val) = + (packet_stats.transport.sctp * 100).checked_div(packet_stats.total) + { + format!("{val}%") + } else { + "0%".to_string() + }, + ) + .value( + if let Some(val) = + (packet_stats.transport.sctp * 100).checked_div(packet_stats.total) + { + val as u64 + } else { + 0 + }, + ), Bar::default() .label("ICMPv4") .style(Style::new().fg(Color::LightCyan)) .value_style(Style::new().fg(Color::Black).bg(Color::LightCyan)) - .text_value(if packet_stats.total != 0 { - format!( - "{}%", - packet_stats.network.icmpv4 * 100 / packet_stats.total - ) - } else { - "0%".to_string() - }) - .value(if packet_stats.total != 0 { - (packet_stats.network.icmpv4 * 100 / packet_stats.total) as u64 - } else { - 0 - }), + .text_value( + if let Some(val) = + (packet_stats.network.icmpv4 * 100).checked_div(packet_stats.total) + { + format!("{val}%") + } else { + "0%".to_string() + }, + ) + .value( + if let Some(val) = + (packet_stats.network.icmpv4 * 100).checked_div(packet_stats.total) + { + val as u64 + } else { + 0 + }, + ), Bar::default() .label("ICMPv6") .style(Style::new().fg(Color::LightCyan)) .value_style(Style::new().fg(Color::Black).bg(Color::LightCyan)) - .text_value(if packet_stats.total != 0 { - format!( - "{}%", - packet_stats.network.icmpv6 * 100 / packet_stats.total - ) - } else { - "0%".to_string() - }) - .value(if packet_stats.total != 0 { - (packet_stats.network.icmpv6 * 100 / packet_stats.total) as u64 - } else { - 0 - }), + .text_value( + if let Some(val) = + (packet_stats.network.icmpv6 * 100).checked_div(packet_stats.total) + { + format!("{val}%") + } else { + "0%".to_string() + }, + ) + .value( + if let Some(val) = + (packet_stats.network.icmpv6 * 100).checked_div(packet_stats.total) + { + val as u64 + } else { + 0 + }, + ), + Bar::default() + .label("IGMP") + .style(Style::new().fg(Color::LightCyan)) + .value_style(Style::new().fg(Color::Black).bg(Color::LightCyan)) + .text_value( + if let Some(val) = + (packet_stats.network.igmp * 100).checked_div(packet_stats.total) + { + format!("{val}%") + } else { + "0%".to_string() + }, + ) + .value( + if let Some(val) = + (packet_stats.network.igmp * 100).checked_div(packet_stats.total) + { + val as u64 + } else { + 0 + }, + ), ]), ) .block(Block::new().padding(Padding::horizontal(1))) @@ -315,30 +383,46 @@ impl Stats { .label("IPv4") .style(Style::new().fg(Color::LightRed)) .value_style(Style::new().fg(Color::Black).bg(Color::LightRed)) - .text_value(if packet_stats.total != 0 { - format!("{}%", packet_stats.network.ipv4 * 100 / packet_stats.total) - } else { - "0%".to_string() - }) - .value(if packet_stats.total != 0 { - (packet_stats.network.ipv4 * 100 / packet_stats.total) as u64 - } else { - 0 - }), + .text_value( + if let Some(val) = + (packet_stats.network.ipv4 * 100).checked_div(packet_stats.total) + { + format!("{val}%") + } else { + "0%".to_string() + }, + ) + .value( + if let Some(val) = + (packet_stats.network.ipv4 * 100).checked_div(packet_stats.total) + { + val as u64 + } else { + 0 + }, + ), Bar::default() .label("IPv6") .style(Style::new().fg(Color::LightCyan)) .value_style(Style::new().fg(Color::Black).bg(Color::LightCyan)) - .text_value(if packet_stats.total != 0 { - format!("{}%", packet_stats.network.ipv6 * 100 / packet_stats.total) - } else { - "0%".to_string() - }) - .value(if packet_stats.total != 0 { - (packet_stats.network.ipv6 * 100 / packet_stats.total) as u64 - } else { - 0 - }), + .text_value( + if let Some(val) = + (packet_stats.network.ipv6 * 100).checked_div(packet_stats.total) + { + format!("{val}%") + } else { + "0%".to_string() + }, + ) + .value( + if let Some(val) = + (packet_stats.network.ipv6 * 100).checked_div(packet_stats.total) + { + val as u64 + } else { + 0 + }, + ), ]), ) .block(Block::new().padding(Padding::horizontal(1))) @@ -389,6 +473,7 @@ pub struct NetworkStats { pub ipv6: usize, pub icmpv4: usize, pub icmpv6: usize, + pub igmp: usize, } #[derive(Debug, Default)]