Add bridge provisioning for networks (root-only)
Commit 3/6 of the network isolation feature (docs/networking-design.md).
network_bridge.{h,cpp}: ensure_network_provisioned() stands up a
network's real bridge -- idempotent (checks `ip link show` first), so
this doubles as the reboot-reconciliation mechanism, no separate code
path. extern's bridge lives in the host's own root namespace with
net.ipv4.ip_forward + an iptables MASQUERADE rule for the subnet (+
IPv6 equivalents if enabled); intern's bridge lives inside its own
dedicated persistent namespace (persistent_netns.h) with no forwarding
or NAT at all -- a structural isolation boundary, not just a missing
rule. Bridge names are a deterministic FNV-1a hash of the network name
(not std::hash, whose value isn't guaranteed stable across a rebuild),
kept under Linux's 15-char interface name limit.
network_subnet.{h,cpp} gains ipv4_gateway_address()/
ipv6_gateway_address() (mask a CIDR to its network address, +1 for the
bridge's own ".1"). create_network_command() now calls
ensure_network_provisioned() before persisting the config entry -- a
network that fails to provision isn't saved.
Verified end-to-end as root (via a scoped doas rule): a real extern
network's bridge/gateway IPs/forwarding/NAT rule, and a real intern
network's isolated bridge with neither, both came up correctly; test
networks removed via --delete-network afterward.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2026 Viorel Munteanu
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config_file.h"
|
||||
|
||||
// Checks that the external tools provisioning `network` needs are found in
|
||||
// PATH, logging which are missing: always `ip`; `iptables`/`sysctl` (+
|
||||
// `ip6tables` if `network.ipv6`) for `extern`; `nsenter` for `intern` (to
|
||||
// reach its dedicated persistent namespace). Same shape/spirit as
|
||||
// commands.cpp's own check_required_dependencies(), kept separate since this
|
||||
// file's tool set depends on the network's own kind/ipv6 setting.
|
||||
bool check_network_dependencies(const NetworkEntry& network);
|
||||
|
||||
// Ensures `network`'s bridge (and, for `intern`, its dedicated persistent
|
||||
// namespace -- persistent_netns.h) exists and is configured, creating
|
||||
// whatever's missing:
|
||||
// - extern: bridge in the host's own root namespace (this whole feature is
|
||||
// root-only for now, see docs/networking-design.md, so no nsenter
|
||||
// wrapping is needed to reach it); net.ipv4.ip_forward=1 (+ the IPv6
|
||||
// forwarding sysctl if network.ipv6) and one iptables MASQUERADE rule
|
||||
// (+ ip6tables if network.ipv6) for the subnet.
|
||||
// - intern: bridge inside network's own dedicated persistent namespace
|
||||
// (created here if it doesn't exist yet); no forwarding sysctl, no NAT
|
||||
// rule -- no route out at all.
|
||||
// Idempotent: a no-op (true) if the bridge already exists. This doubles as
|
||||
// the mechanism that transparently recreates a network's host-side state
|
||||
// after a reboot (nothing about it survives one except the config.yaml
|
||||
// entry) -- there's no separate "reconcile" path; calling this again just
|
||||
// recreates whatever's missing.
|
||||
bool ensure_network_provisioned(const NetworkEntry& network);
|
||||
Reference in New Issue
Block a user