package daemon import ( "context" "banger/internal/hostnat" "banger/internal/model" "banger/internal/system" ) type natRule = hostnat.Rule func (d *Daemon) ensureNAT(ctx context.Context, vm model.VMRecord, enable bool) error { return hostnat.Ensure(ctx, d.runner, vm.Runtime.GuestIP, d.vmHandles(vm.ID).TapDevice, enable) } func (d *Daemon) validateNATPrereqs(ctx context.Context) (string, error) { checks := system.NewPreflight() checks.RequireCommand("ip", toolHint("ip")) d.addNATPrereqs(ctx, checks) if err := checks.Err("nat preflight failed"); err != nil { return "", err } return d.defaultUplink(ctx) } func (d *Daemon) defaultUplink(ctx context.Context) (string, error) { return hostnat.DefaultUplink(ctx, d.runner) } func parseDefaultUplink(output string) (string, error) { return hostnat.ParseDefaultUplink(output) } // natRulesForVM builds the iptables rule set for vm + tap + uplink. // tap is passed explicitly (rather than read from a handle cache) // because natRulesForVM has no Daemon receiver — it's usable from // test helpers that build rule expectations without a daemon. func natRulesForVM(vm model.VMRecord, tap, uplink string) ([]natRule, error) { return hostnat.Rules(vm.Runtime.GuestIP, tap, uplink) } func natRuleArgs(action string, rule natRule) []string { return hostnat.RuleArgs(action, rule) } func natAddPlan(rules []natRule) [][]string { return hostnat.AddPlan(rules) } func natRemovePlan(rules []natRule) [][]string { return hostnat.RemovePlan(rules) } func natRuleKey(rule natRule) string { return hostnat.RuleKey(rule) }