| 379 | |
| 380 | impl Drop for NetworkNamespace { |
| 381 | fn drop(&mut self) { |
| 382 | debug!(namespace = %self.name, "Cleaning up network namespace"); |
| 383 | |
| 384 | // Close the fd if we have one |
| 385 | if let Some(fd) = self.ns_fd.take() { |
| 386 | let _ = nix::unistd::close(fd); |
| 387 | } |
| 388 | |
| 389 | // Delete the host-side veth (this also removes the peer) |
| 390 | if let Err(e) = run_ip(&["link", "delete", &self.veth_host]) { |
| 391 | warn!( |
| 392 | error = %e, |
| 393 | veth = %self.veth_host, |
| 394 | "Failed to delete veth interface" |
| 395 | ); |
| 396 | } |
| 397 | |
| 398 | // Delete the namespace |
| 399 | if let Err(e) = run_ip(&["netns", "delete", &self.name]) { |
| 400 | warn!( |
| 401 | error = %e, |
| 402 | namespace = %self.name, |
| 403 | "Failed to delete network namespace" |
| 404 | ); |
| 405 | } |
| 406 | |
| 407 | openshell_ocsf::ocsf_emit!( |
| 408 | openshell_ocsf::ConfigStateChangeBuilder::new(openshell_ocsf::ctx::ctx()) |
| 409 | .severity(openshell_ocsf::SeverityId::Informational) |
| 410 | .status(openshell_ocsf::StatusId::Success) |
| 411 | .state(openshell_ocsf::StateId::Disabled, "cleaned_up") |
| 412 | .message(format!("Network namespace cleaned up [ns:{}]", self.name)) |
| 413 | .build() |
| 414 | ); |
| 415 | } |
| 416 | } |
| 417 | |
| 418 | /// Create the workload's network namespace and install bypass detection |