Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion cmd/daemon/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package daemon

import (
"context"
"net"
"time"

"github.com/abiosoft/colima/cmd/root"
Expand Down Expand Up @@ -32,7 +33,7 @@ var startCmd = &cobra.Command{

var processes []process.Process
if daemonArgs.vmnet.enabled {
processes = append(processes, vmnet.New(daemonArgs.vmnet.mode, daemonArgs.vmnet.netInterface, daemonArgs.vmnet.subnet))
processes = append(processes, vmnet.New(daemonArgs.vmnet.mode, daemonArgs.vmnet.netInterface, daemonArgs.vmnet.subnet, daemonArgs.vmnet.nat66Prefix))
}
if daemonArgs.inotify.enabled {
processes = append(processes, inotify.New())
Expand Down Expand Up @@ -84,6 +85,7 @@ var daemonArgs struct {
mode string
netInterface string
subnet config.Subnet
nat66Prefix net.IP
}
inotify struct {
enabled bool
Expand All @@ -107,6 +109,7 @@ func init() {
startCmd.Flags().StringVar(&daemonArgs.vmnet.subnet.Gateway, "vmnet-gateway", config.NetGateway, "vmnet gateway for shared mode")
startCmd.Flags().StringVar(&daemonArgs.vmnet.subnet.DHCPEnd, "vmnet-dhcp-end", config.NetDHCPEnd, "vmnet DHCP end address for shared mode")
startCmd.Flags().StringVar(&daemonArgs.vmnet.subnet.Netmask, "vmnet-mask", config.NetMask, "vmnet mask for shared mode")
startCmd.Flags().IPVar(&daemonArgs.vmnet.nat66Prefix, "vmnet-nat66-prefix", nil, "vmnet nat66 ULA prefix for shared mode")
startCmd.Flags().BoolVar(&daemonArgs.inotify.enabled, "inotify", false, "start inotify")
startCmd.Flags().StringSliceVar(&daemonArgs.inotify.dirs, "inotify-dir", nil, "set inotify directories")
startCmd.Flags().StringVar(&daemonArgs.inotify.runtime, "inotify-runtime", "docker", "set runtime")
Expand Down
6 changes: 6 additions & 0 deletions cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ func init() {
startCmd.Flags().StringVar(&startCmdArgs.Network.BridgeInterface, "network-interface", "en0", "host network interface to use for bridged mode")
startCmd.Flags().BoolVar(&startCmdArgs.Network.PreferredRoute, "network-preferred-route", false, "use the assigned IP address as the preferred route for the VM (implies --network-address)")

// nat66 prefix
startCmd.Flags().IPVar(&startCmdArgs.Network.NAT66Prefix, "network-nat66-prefix", nil, "nat66 ULA prefix for shared mode (optional, e.g. fd25:636f:6c69:6d61::)")

// vm type
if util.MacOS13OrNewer() {
startCmd.Flags().StringVarP(&startCmdArgs.VMType, "vm-type", "t", defaultVMType, "virtual machine type ("+types+")")
Expand Down Expand Up @@ -639,6 +642,9 @@ func prepareConfig(cmd *cobra.Command) {
if !cmd.Flag("network-subnet").Changed {
startCmdArgs.Network.Subnet = current.Network.Subnet
}
if !cmd.Flag("network-nat66-prefix").Changed {
startCmdArgs.Network.NAT66Prefix = current.Network.NAT66Prefix
}
if !cmd.Flag("network-interface").Changed {
startCmdArgs.Network.BridgeInterface = current.Network.BridgeInterface
}
Expand Down
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ type Kubernetes struct {
type Network struct {
Address bool `yaml:"address"`
Subnet string `yaml:"subnet,omitempty"`
NAT66Prefix net.IP `yaml:"nat66Prefix,omitempty"`
DNSResolvers []net.IP `yaml:"dns"`
DNSHosts map[string]string `yaml:"dnsHosts"`
HostAddresses bool `yaml:"hostAddresses"`
Expand Down
22 changes: 22 additions & 0 deletions config/configmanager/configmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,13 @@ func ValidateConfig(c config.Config) error {
return err
}
}

if err := validateNetworkSubnet(c); err != nil {
return err
}
if err := validateNetworkNat66Prefix(c); err != nil {
return err
}

if err := validateMounts(c.Mounts); err != nil {
return err
Expand All @@ -124,6 +128,24 @@ func validateNetworkSubnet(c config.Config) error {
return nil
}

func validateNetworkNat66Prefix(c config.Config) error {
prefix := c.Network.NAT66Prefix
if prefix == nil {
return nil
}
ip6 := prefix.To16()
if prefix.To4() != nil || ip6 == nil || ip6[0] != 0xfd || !ip6.Equal(ip6.Mask(net.CIDRMask(64, 128))) {
return fmt.Errorf("network nat66Prefix %q must be an IPv6 ULA address with its lower 64 bits set to zero", prefix)
}
if c.Network.Mode != "shared" {
return fmt.Errorf("network nat66Prefix is only supported with shared network mode")
}
if c.VMType == "vz" {
return fmt.Errorf("network nat66Prefix is not supported with vmType 'vz'")
}
return nil
}

// Load loads the config.
// Error is only returned if the config file exists but could not be loaded.
// No error is returned if the config file does not exist.
Expand Down
6 changes: 5 additions & 1 deletion daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ func (l processManager) Start(ctx context.Context, conf config.Config) error {
args = append(args, "--vmnet-gateway", subnet.Gateway)
args = append(args, "--vmnet-dhcp-end", subnet.DHCPEnd)
args = append(args, "--vmnet-mask", subnet.Netmask)

if conf.Network.NAT66Prefix != nil {
args = append(args, "--vmnet-nat66-prefix", conf.Network.NAT66Prefix.String())
}
}
if conf.MountINotify {
args = append(args, "--inotify")
Expand Down Expand Up @@ -142,7 +146,7 @@ func processesFromConfig(conf config.Config) []process.Process {

if conf.Network.Address {
subnet, _ := config.ParseSubnet(conf.Network.Subnet)
processes = append(processes, vmnet.New(conf.Network.Mode, conf.Network.BridgeInterface, subnet))
processes = append(processes, vmnet.New(conf.Network.Mode, conf.Network.BridgeInterface, subnet, conf.Network.NAT66Prefix))
}
if conf.MountINotify {
processes = append(processes, inotify.New())
Expand Down
13 changes: 11 additions & 2 deletions daemon/process/vmnet/vmnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,20 @@ const SubProcessEnvVar = "COLIMA_VMNET"

var _ process.Process = (*vmnetProcess)(nil)

func New(mode, netInterface string, subnet config.Subnet) process.Process {
func New(mode, netInterface string, subnet config.Subnet, nat66Prefix net.IP) process.Process {
return &vmnetProcess{
mode: mode,
netInterface: netInterface,
subnet: subnet,
nat66Prefix: nat66Prefix,
}
}

type vmnetProcess struct {
mode string
netInterface string
subnet config.Subnet
nat66Prefix net.IP
}

func (*vmnetProcess) Alive(ctx context.Context) error {
Expand Down Expand Up @@ -89,15 +91,22 @@ func (v *vmnetProcess) Start(ctx context.Context) error {
socket,
)
} else {
command = cli.CommandInteractive("sudo", BinaryPath,
args := []string{
BinaryPath,
"--vmnet-mode", "shared",
"--socket-group", "staff",
"--vmnet-gateway", v.subnet.Gateway,
"--vmnet-dhcp-end", v.subnet.DHCPEnd,
"--vmnet-mask", v.subnet.Netmask,
}
if v.nat66Prefix != nil {
args = append(args, "--vmnet-nat66-prefix", v.nat66Prefix.String())
}
args = append(args,
"--pidfile", pid,
socket,
)
command = cli.CommandInteractive("sudo", args...)
}

if cli.Settings.Verbose {
Expand Down
7 changes: 7 additions & 0 deletions embedded/defaults/colima.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ network:
# Default: 192.168.106.0/24
subnet: ""

# IPv6 ULA prefix for NAT66 for shared mode.
# This is only supported when mode is set to shared.
# This setting is not supported by VZ.
# Chosen automatically by macOS if unset
# Default: null
nat66Prefix: null

# Network interface to use for bridged mode.
# This is only used when mode is set to bridged.
# NOTE: this is currently macOS only and ignored on Linux.
Expand Down
4 changes: 4 additions & 0 deletions util/yamlutil/yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func Test_encode_Docker(t *testing.T) {
Network: config.Network{
DNSResolvers: []net.IP{net.ParseIP("1.1.1.1")},
Subnet: "192.168.107.0/24",
NAT66Prefix: net.ParseIP("fd25:636f:6c69:6d61::"),
},
Kubernetes: config.Kubernetes{K3sArgs: []string{"--disable=traefik"}},
}
Expand Down Expand Up @@ -43,6 +44,9 @@ func Test_encode_Docker(t *testing.T) {
if !reflect.DeepEqual(got.Docker, tt.want.Docker) {
t.Errorf("save() = %+v\nwant %+v", got.Docker, tt.want.Docker)
}
if !got.Network.NAT66Prefix.Equal(tt.want.Network.NAT66Prefix) {
t.Errorf("nat66Prefix = %q, want %q", got.Network.NAT66Prefix, tt.want.Network.NAT66Prefix)
}
if got.Network.Subnet != tt.want.Network.Subnet {
t.Errorf("network subnet = %q, want %q", got.Network.Subnet, tt.want.Network.Subnet)
}
Expand Down
Loading