├── .gitignore ├── README.md ├── Cargo.toml ├── LICENSE ├── src └── main.rs └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # container-networking 2 | 3 | This is a proof of concept for setting up networking for a container. 4 | 5 | ## Usage 6 | 7 | > [!WARNING] 8 | > Running this requires root privileges and may be destructive. 9 | 10 | ```bash 11 | cargo build --release 12 | sudo ./target/release/networking-test 13 | ``` 14 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "container-networking" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | anyhow = "1.0.89" 8 | futures = "0.3.31" 9 | ipnetwork = "0.20.0" 10 | mnl = "0.2.2" 11 | nftnl = "0.7.0" 12 | nix = { version = "0.29.0", features = ["sched"] } 13 | rtnetlink = "0.14.1" 14 | tokio = { version = "1.40.0", features = ["full"] } 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 David Mo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::{ffi::CString, net::Ipv4Addr, os::fd::AsRawFd}; 2 | 3 | use anyhow::{bail, Result}; 4 | use futures::TryStreamExt; 5 | use ipnetwork::{IpNetwork, Ipv4Network}; 6 | use nftnl::{nft_expr, ChainType, Hook, MsgType, ProtoFamily}; 7 | use nix::{ 8 | libc, 9 | sched::{setns, CloneFlags}, 10 | }; 11 | use rtnetlink::NetworkNamespace; 12 | use tokio::fs::File; 13 | 14 | const PREFIX_LENGTH: u8 = 16; 15 | 16 | #[tokio::main] 17 | async fn main() -> Result<()> { 18 | let (connection, handle, _) = rtnetlink::new_connection()?; 19 | tokio::spawn(connection); 20 | 21 | let bridge_ip = Ipv4Addr::new(172, 18, 0, 1); 22 | let bridge_net = IpNetwork::V4(Ipv4Network::new(bridge_ip, PREFIX_LENGTH)?); 23 | let bridge_idx = create_bridge(&handle, "br0", &bridge_net).await?; 24 | let (veth_idx, ceth_idx) = create_veth_pair(&handle, "veth0", "ceth0").await?; 25 | handle 26 | .link() 27 | .set(veth_idx) 28 | .controller(bridge_idx) 29 | .execute() 30 | .await?; 31 | 32 | let ns_file = create_namespace("netns0").await?; 33 | handle 34 | .link() 35 | .set(ceth_idx) 36 | .setns_by_fd(ns_file.as_raw_fd()) 37 | .execute() 38 | .await?; 39 | 40 | let veth_ip = Ipv4Addr::new(172, 18, 0, 2); 41 | let veth_net = IpNetwork::V4(Ipv4Network::new(veth_ip, PREFIX_LENGTH)?); 42 | setup_veth_peer(&ns_file, "ceth0", &veth_net, bridge_ip).await?; 43 | 44 | let network_ip = Ipv4Addr::new(172, 18, 0, 0); 45 | let container_net = IpNetwork::V4(Ipv4Network::new(network_ip, PREFIX_LENGTH)?); 46 | create_nat(&container_net, "br0")?; 47 | 48 | Ok(()) 49 | } 50 | 51 | /// Gets the index of a link by name. 52 | async fn get_index(handle: &rtnetlink::Handle, name: &str) -> Result { 53 | let mut links = handle.link().get().match_name(name.to_string()).execute(); 54 | if let Some(link) = links.try_next().await? { 55 | Ok(link.header.index) 56 | } else { 57 | bail!("Link {} not found", name); 58 | } 59 | } 60 | 61 | /// Creates a bridge. Equivalent to: 62 | /// ```bash 63 | /// ip link add NAME type bridge 64 | /// ip addr add ADDRESS/PREFIX_LENGTH dev NAME 65 | /// ip link set NAME up 66 | /// ``` 67 | async fn create_bridge(handle: &rtnetlink::Handle, name: &str, network: &IpNetwork) -> Result { 68 | handle 69 | .link() 70 | .add() 71 | .bridge(name.to_string()) 72 | .execute() 73 | .await?; 74 | let index = get_index(handle, name).await?; 75 | handle 76 | .address() 77 | .add(index, network.ip(), network.prefix()) 78 | .execute() 79 | .await?; 80 | handle.link().set(index).up().execute().await?; 81 | Ok(index) 82 | } 83 | 84 | /// Creates a network namespace. Equivalent to: 85 | /// ```bash 86 | /// ip netns add NAME 87 | /// ``` 88 | async fn create_namespace(name: &str) -> Result { 89 | NetworkNamespace::add(name.to_string()).await?; 90 | let ns_filename = format!("/var/run/netns/{}", name); 91 | let tokio_ns_file = File::open(&ns_filename).await?; 92 | let ns_file = tokio_ns_file.into_std().await; 93 | Ok(ns_file) 94 | } 95 | 96 | /// Creates a veth pair. Equivalent to: 97 | /// ```bash 98 | /// ip link add NAME type veth peer name PEER_NAME 99 | /// ip link set NAME up 100 | /// ``` 101 | async fn create_veth_pair( 102 | handle: &rtnetlink::Handle, 103 | name: &str, 104 | peer_name: &str, 105 | ) -> Result<(u32, u32)> { 106 | handle 107 | .link() 108 | .add() 109 | .veth(name.to_string(), peer_name.to_string()) 110 | .execute() 111 | .await?; 112 | let veth_idx = get_index(handle, name).await?; 113 | let ceth_idx = get_index(handle, peer_name).await?; 114 | handle.link().set(veth_idx).up().execute().await?; 115 | Ok((veth_idx, ceth_idx)) 116 | } 117 | 118 | /// Sets up the veth peer in the netns namespace. Equivalent to: 119 | /// ```bash 120 | /// nsenter --net=NS_FILE bash 121 | /// ip link set lo up 122 | /// ip link set PEER_NAME up 123 | /// ip addr add ADDRESS/PREFIX_LENGTH dev PEER_NAME 124 | /// ip route add default via BRIDGE_ADDRESS 125 | /// ``` 126 | async fn setup_veth_peer( 127 | ns_file: &std::fs::File, 128 | peer_name: &str, 129 | network: &IpNetwork, 130 | bridge_address: Ipv4Addr, 131 | ) -> Result<()> { 132 | let init_netns = File::open("/proc/1/ns/net").await?; 133 | setns(ns_file, CloneFlags::CLONE_NEWNET)?; 134 | let (connection, handle, _) = rtnetlink::new_connection()?; 135 | tokio::spawn(connection); 136 | setns(init_netns, CloneFlags::CLONE_NEWNET)?; 137 | let lo_idx = get_index(&handle, "lo").await?; 138 | handle.link().set(lo_idx).up().execute().await?; 139 | let ceth_idx = get_index(&handle, peer_name).await?; 140 | handle.link().set(ceth_idx).up().execute().await?; 141 | handle 142 | .address() 143 | .add(ceth_idx, network.ip(), network.prefix()) 144 | .execute() 145 | .await?; 146 | handle 147 | .route() 148 | .add() 149 | .v4() 150 | .destination_prefix(Ipv4Addr::UNSPECIFIED, 0) 151 | .gateway(bridge_address) 152 | .execute() 153 | .await?; 154 | Ok(()) 155 | } 156 | 157 | /// Creates a NAT table and chain for the given network. 158 | fn create_nat(network: &IpNetwork, bridge_device: &str) -> Result<()> { 159 | let mut batch = nftnl::Batch::new(); 160 | let table = nftnl::Table::new(&CString::new("container-nat")?, ProtoFamily::Ipv4); 161 | batch.add(&table, MsgType::Add); 162 | 163 | let mut chain = nftnl::Chain::new(&CString::new("postrouting-chain")?, &table); 164 | chain.set_hook(Hook::PostRouting, libc::NF_IP_PRI_NAT_SRC); 165 | chain.set_type(ChainType::Nat); 166 | batch.add(&chain, MsgType::Add); 167 | 168 | let mut rule = nftnl::Rule::new(&chain); 169 | // match on the packet's source address 170 | rule.add_expr(&nft_expr!(payload ipv4 saddr)); 171 | rule.add_expr(&nft_expr!(bitwise mask network.mask(), xor 0)); 172 | rule.add_expr(&nft_expr!(cmp == network.ip())); 173 | // match interface 174 | rule.add_expr(&nft_expr!(meta oifname)); 175 | rule.add_expr(&nft_expr!(cmp != bridge_device)); 176 | //apply masquerade 177 | rule.add_expr(&nft_expr!(masquerade)); 178 | batch.add(&rule, MsgType::Add); 179 | 180 | let finalized_batch = batch.finalize(); 181 | send_and_process(&finalized_batch)?; 182 | Ok(()) 183 | } 184 | 185 | // Taken from https://github.com/mullvad/nftnl-rs/blob/main/nftnl/examples/add-rules.rs 186 | fn send_and_process(batch: &nftnl::FinalizedBatch) -> Result<()> { 187 | // Create a netlink socket to netfilter. 188 | let socket = mnl::Socket::new(mnl::Bus::Netfilter)?; 189 | // Send all the bytes in the batch. 190 | socket.send_all(batch)?; 191 | 192 | // Try to parse the messages coming back from netfilter. This part is still very unclear. 193 | let portid = socket.portid(); 194 | let mut buffer = vec![0; nftnl::nft_nlmsg_maxsize() as usize]; 195 | let very_unclear_what_this_is_for = 2; 196 | while let Some(message) = socket_recv(&socket, &mut buffer[..])? { 197 | match mnl::cb_run(message, very_unclear_what_this_is_for, portid)? { 198 | mnl::CbResult::Stop => { 199 | break; 200 | } 201 | mnl::CbResult::Ok => (), 202 | } 203 | } 204 | Ok(()) 205 | } 206 | 207 | // Taken from https://github.com/mullvad/nftnl-rs/blob/main/nftnl/examples/add-rules.rs 208 | fn socket_recv<'a>(socket: &mnl::Socket, buf: &'a mut [u8]) -> Result> { 209 | let ret = socket.recv(buf)?; 210 | if ret > 0 { 211 | Ok(Some(&buf[..ret])) 212 | } else { 213 | Ok(None) 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "anyhow" 22 | version = "1.0.89" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" 25 | 26 | [[package]] 27 | name = "autocfg" 28 | version = "1.4.0" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 31 | 32 | [[package]] 33 | name = "backtrace" 34 | version = "0.3.74" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 37 | dependencies = [ 38 | "addr2line", 39 | "cfg-if", 40 | "libc", 41 | "miniz_oxide", 42 | "object", 43 | "rustc-demangle", 44 | "windows-targets", 45 | ] 46 | 47 | [[package]] 48 | name = "bitflags" 49 | version = "2.6.0" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 52 | 53 | [[package]] 54 | name = "byteorder" 55 | version = "1.5.0" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 58 | 59 | [[package]] 60 | name = "bytes" 61 | version = "1.7.2" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" 64 | 65 | [[package]] 66 | name = "cfg-if" 67 | version = "1.0.0" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 70 | 71 | [[package]] 72 | name = "cfg_aliases" 73 | version = "0.2.1" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 76 | 77 | [[package]] 78 | name = "container-networking" 79 | version = "0.1.0" 80 | dependencies = [ 81 | "anyhow", 82 | "futures", 83 | "ipnetwork", 84 | "mnl", 85 | "nftnl", 86 | "nix 0.29.0", 87 | "rtnetlink", 88 | "tokio", 89 | ] 90 | 91 | [[package]] 92 | name = "futures" 93 | version = "0.3.31" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 96 | dependencies = [ 97 | "futures-channel", 98 | "futures-core", 99 | "futures-executor", 100 | "futures-io", 101 | "futures-sink", 102 | "futures-task", 103 | "futures-util", 104 | ] 105 | 106 | [[package]] 107 | name = "futures-channel" 108 | version = "0.3.31" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 111 | dependencies = [ 112 | "futures-core", 113 | "futures-sink", 114 | ] 115 | 116 | [[package]] 117 | name = "futures-core" 118 | version = "0.3.31" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 121 | 122 | [[package]] 123 | name = "futures-executor" 124 | version = "0.3.31" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 127 | dependencies = [ 128 | "futures-core", 129 | "futures-task", 130 | "futures-util", 131 | ] 132 | 133 | [[package]] 134 | name = "futures-io" 135 | version = "0.3.31" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 138 | 139 | [[package]] 140 | name = "futures-macro" 141 | version = "0.3.31" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 144 | dependencies = [ 145 | "proc-macro2", 146 | "quote", 147 | "syn", 148 | ] 149 | 150 | [[package]] 151 | name = "futures-sink" 152 | version = "0.3.31" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 155 | 156 | [[package]] 157 | name = "futures-task" 158 | version = "0.3.31" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 161 | 162 | [[package]] 163 | name = "futures-util" 164 | version = "0.3.31" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 167 | dependencies = [ 168 | "futures-channel", 169 | "futures-core", 170 | "futures-io", 171 | "futures-macro", 172 | "futures-sink", 173 | "futures-task", 174 | "memchr", 175 | "pin-project-lite", 176 | "pin-utils", 177 | "slab", 178 | ] 179 | 180 | [[package]] 181 | name = "gimli" 182 | version = "0.31.1" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 185 | 186 | [[package]] 187 | name = "hermit-abi" 188 | version = "0.3.9" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 191 | 192 | [[package]] 193 | name = "ipnetwork" 194 | version = "0.20.0" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" 197 | dependencies = [ 198 | "serde", 199 | ] 200 | 201 | [[package]] 202 | name = "libc" 203 | version = "0.2.160" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "f0b21006cd1874ae9e650973c565615676dc4a274c965bb0a73796dac838ce4f" 206 | 207 | [[package]] 208 | name = "lock_api" 209 | version = "0.4.12" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 212 | dependencies = [ 213 | "autocfg", 214 | "scopeguard", 215 | ] 216 | 217 | [[package]] 218 | name = "log" 219 | version = "0.4.22" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 222 | 223 | [[package]] 224 | name = "memchr" 225 | version = "2.7.4" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 228 | 229 | [[package]] 230 | name = "miniz_oxide" 231 | version = "0.8.0" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" 234 | dependencies = [ 235 | "adler2", 236 | ] 237 | 238 | [[package]] 239 | name = "mio" 240 | version = "1.0.2" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" 243 | dependencies = [ 244 | "hermit-abi", 245 | "libc", 246 | "wasi", 247 | "windows-sys", 248 | ] 249 | 250 | [[package]] 251 | name = "mnl" 252 | version = "0.2.2" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "d1a5469630da93e1813bb257964c0ccee3b26b6879dd858039ddec35cc8681ed" 255 | dependencies = [ 256 | "libc", 257 | "log", 258 | "mnl-sys", 259 | ] 260 | 261 | [[package]] 262 | name = "mnl-sys" 263 | version = "0.2.1" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "9750685b201e1ecfaaf7aa5d0387829170fa565989cc481b49080aa155f70457" 266 | dependencies = [ 267 | "libc", 268 | "pkg-config", 269 | ] 270 | 271 | [[package]] 272 | name = "netlink-packet-core" 273 | version = "0.7.0" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" 276 | dependencies = [ 277 | "anyhow", 278 | "byteorder", 279 | "netlink-packet-utils", 280 | ] 281 | 282 | [[package]] 283 | name = "netlink-packet-route" 284 | version = "0.19.0" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "74c171cd77b4ee8c7708da746ce392440cb7bcf618d122ec9ecc607b12938bf4" 287 | dependencies = [ 288 | "anyhow", 289 | "byteorder", 290 | "libc", 291 | "log", 292 | "netlink-packet-core", 293 | "netlink-packet-utils", 294 | ] 295 | 296 | [[package]] 297 | name = "netlink-packet-utils" 298 | version = "0.5.2" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" 301 | dependencies = [ 302 | "anyhow", 303 | "byteorder", 304 | "paste", 305 | "thiserror", 306 | ] 307 | 308 | [[package]] 309 | name = "netlink-proto" 310 | version = "0.11.3" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "86b33524dc0968bfad349684447bfce6db937a9ac3332a1fe60c0c5a5ce63f21" 313 | dependencies = [ 314 | "bytes", 315 | "futures", 316 | "log", 317 | "netlink-packet-core", 318 | "netlink-sys", 319 | "thiserror", 320 | "tokio", 321 | ] 322 | 323 | [[package]] 324 | name = "netlink-sys" 325 | version = "0.8.6" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | checksum = "416060d346fbaf1f23f9512963e3e878f1a78e707cb699ba9215761754244307" 328 | dependencies = [ 329 | "bytes", 330 | "futures", 331 | "libc", 332 | "log", 333 | "tokio", 334 | ] 335 | 336 | [[package]] 337 | name = "nftnl" 338 | version = "0.7.0" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | checksum = "06a7491dd91b71643f65546389f25506da70723d1f1ec8c8d6d20444d1c23f27" 341 | dependencies = [ 342 | "bitflags", 343 | "log", 344 | "nftnl-sys", 345 | ] 346 | 347 | [[package]] 348 | name = "nftnl-sys" 349 | version = "0.6.2" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "b193f2c2a70e6421534c3f3b75eaaed4e4b9df45281b3d94f5bc8c32fb346cbb" 352 | dependencies = [ 353 | "cfg-if", 354 | "libc", 355 | "pkg-config", 356 | ] 357 | 358 | [[package]] 359 | name = "nix" 360 | version = "0.27.1" 361 | source = "registry+https://github.com/rust-lang/crates.io-index" 362 | checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" 363 | dependencies = [ 364 | "bitflags", 365 | "cfg-if", 366 | "libc", 367 | ] 368 | 369 | [[package]] 370 | name = "nix" 371 | version = "0.29.0" 372 | source = "registry+https://github.com/rust-lang/crates.io-index" 373 | checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" 374 | dependencies = [ 375 | "bitflags", 376 | "cfg-if", 377 | "cfg_aliases", 378 | "libc", 379 | ] 380 | 381 | [[package]] 382 | name = "object" 383 | version = "0.36.5" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" 386 | dependencies = [ 387 | "memchr", 388 | ] 389 | 390 | [[package]] 391 | name = "parking_lot" 392 | version = "0.12.3" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 395 | dependencies = [ 396 | "lock_api", 397 | "parking_lot_core", 398 | ] 399 | 400 | [[package]] 401 | name = "parking_lot_core" 402 | version = "0.9.10" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 405 | dependencies = [ 406 | "cfg-if", 407 | "libc", 408 | "redox_syscall", 409 | "smallvec", 410 | "windows-targets", 411 | ] 412 | 413 | [[package]] 414 | name = "paste" 415 | version = "1.0.15" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 418 | 419 | [[package]] 420 | name = "pin-project-lite" 421 | version = "0.2.14" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 424 | 425 | [[package]] 426 | name = "pin-utils" 427 | version = "0.1.0" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 430 | 431 | [[package]] 432 | name = "pkg-config" 433 | version = "0.3.31" 434 | source = "registry+https://github.com/rust-lang/crates.io-index" 435 | checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" 436 | 437 | [[package]] 438 | name = "proc-macro2" 439 | version = "1.0.88" 440 | source = "registry+https://github.com/rust-lang/crates.io-index" 441 | checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" 442 | dependencies = [ 443 | "unicode-ident", 444 | ] 445 | 446 | [[package]] 447 | name = "quote" 448 | version = "1.0.37" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" 451 | dependencies = [ 452 | "proc-macro2", 453 | ] 454 | 455 | [[package]] 456 | name = "redox_syscall" 457 | version = "0.5.7" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" 460 | dependencies = [ 461 | "bitflags", 462 | ] 463 | 464 | [[package]] 465 | name = "rtnetlink" 466 | version = "0.14.1" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "b684475344d8df1859ddb2d395dd3dac4f8f3422a1aa0725993cb375fc5caba5" 469 | dependencies = [ 470 | "futures", 471 | "log", 472 | "netlink-packet-core", 473 | "netlink-packet-route", 474 | "netlink-packet-utils", 475 | "netlink-proto", 476 | "netlink-sys", 477 | "nix 0.27.1", 478 | "thiserror", 479 | "tokio", 480 | ] 481 | 482 | [[package]] 483 | name = "rustc-demangle" 484 | version = "0.1.24" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 487 | 488 | [[package]] 489 | name = "scopeguard" 490 | version = "1.2.0" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 493 | 494 | [[package]] 495 | name = "serde" 496 | version = "1.0.210" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" 499 | dependencies = [ 500 | "serde_derive", 501 | ] 502 | 503 | [[package]] 504 | name = "serde_derive" 505 | version = "1.0.210" 506 | source = "registry+https://github.com/rust-lang/crates.io-index" 507 | checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" 508 | dependencies = [ 509 | "proc-macro2", 510 | "quote", 511 | "syn", 512 | ] 513 | 514 | [[package]] 515 | name = "signal-hook-registry" 516 | version = "1.4.2" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 519 | dependencies = [ 520 | "libc", 521 | ] 522 | 523 | [[package]] 524 | name = "slab" 525 | version = "0.4.9" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 528 | dependencies = [ 529 | "autocfg", 530 | ] 531 | 532 | [[package]] 533 | name = "smallvec" 534 | version = "1.13.2" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 537 | 538 | [[package]] 539 | name = "socket2" 540 | version = "0.5.7" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" 543 | dependencies = [ 544 | "libc", 545 | "windows-sys", 546 | ] 547 | 548 | [[package]] 549 | name = "syn" 550 | version = "2.0.79" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" 553 | dependencies = [ 554 | "proc-macro2", 555 | "quote", 556 | "unicode-ident", 557 | ] 558 | 559 | [[package]] 560 | name = "thiserror" 561 | version = "1.0.64" 562 | source = "registry+https://github.com/rust-lang/crates.io-index" 563 | checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" 564 | dependencies = [ 565 | "thiserror-impl", 566 | ] 567 | 568 | [[package]] 569 | name = "thiserror-impl" 570 | version = "1.0.64" 571 | source = "registry+https://github.com/rust-lang/crates.io-index" 572 | checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" 573 | dependencies = [ 574 | "proc-macro2", 575 | "quote", 576 | "syn", 577 | ] 578 | 579 | [[package]] 580 | name = "tokio" 581 | version = "1.40.0" 582 | source = "registry+https://github.com/rust-lang/crates.io-index" 583 | checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" 584 | dependencies = [ 585 | "backtrace", 586 | "bytes", 587 | "libc", 588 | "mio", 589 | "parking_lot", 590 | "pin-project-lite", 591 | "signal-hook-registry", 592 | "socket2", 593 | "tokio-macros", 594 | "windows-sys", 595 | ] 596 | 597 | [[package]] 598 | name = "tokio-macros" 599 | version = "2.4.0" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" 602 | dependencies = [ 603 | "proc-macro2", 604 | "quote", 605 | "syn", 606 | ] 607 | 608 | [[package]] 609 | name = "unicode-ident" 610 | version = "1.0.13" 611 | source = "registry+https://github.com/rust-lang/crates.io-index" 612 | checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" 613 | 614 | [[package]] 615 | name = "wasi" 616 | version = "0.11.0+wasi-snapshot-preview1" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 619 | 620 | [[package]] 621 | name = "windows-sys" 622 | version = "0.52.0" 623 | source = "registry+https://github.com/rust-lang/crates.io-index" 624 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 625 | dependencies = [ 626 | "windows-targets", 627 | ] 628 | 629 | [[package]] 630 | name = "windows-targets" 631 | version = "0.52.6" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 634 | dependencies = [ 635 | "windows_aarch64_gnullvm", 636 | "windows_aarch64_msvc", 637 | "windows_i686_gnu", 638 | "windows_i686_gnullvm", 639 | "windows_i686_msvc", 640 | "windows_x86_64_gnu", 641 | "windows_x86_64_gnullvm", 642 | "windows_x86_64_msvc", 643 | ] 644 | 645 | [[package]] 646 | name = "windows_aarch64_gnullvm" 647 | version = "0.52.6" 648 | source = "registry+https://github.com/rust-lang/crates.io-index" 649 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 650 | 651 | [[package]] 652 | name = "windows_aarch64_msvc" 653 | version = "0.52.6" 654 | source = "registry+https://github.com/rust-lang/crates.io-index" 655 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 656 | 657 | [[package]] 658 | name = "windows_i686_gnu" 659 | version = "0.52.6" 660 | source = "registry+https://github.com/rust-lang/crates.io-index" 661 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 662 | 663 | [[package]] 664 | name = "windows_i686_gnullvm" 665 | version = "0.52.6" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 668 | 669 | [[package]] 670 | name = "windows_i686_msvc" 671 | version = "0.52.6" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 674 | 675 | [[package]] 676 | name = "windows_x86_64_gnu" 677 | version = "0.52.6" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 680 | 681 | [[package]] 682 | name = "windows_x86_64_gnullvm" 683 | version = "0.52.6" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 686 | 687 | [[package]] 688 | name = "windows_x86_64_msvc" 689 | version = "0.52.6" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 692 | --------------------------------------------------------------------------------