diff --git a/pkg/cidata/cidata.TEMPLATE.d/network-config b/pkg/cidata/cidata.TEMPLATE.d/network-config index 706964a0b44..3591dd676fb 100644 --- a/pkg/cidata/cidata.TEMPLATE.d/network-config +++ b/pkg/cidata/cidata.TEMPLATE.d/network-config @@ -6,4 +6,11 @@ ethernets: macaddress: '{{$nw.MACAddress}}' dhcp4: true set-name: {{$nw.Name}} + {{- if and (eq $nw.Name $.SlirpNICName) (gt (len $.DNSAddresses) 0) }} + nameservers: + addresses: + {{- range $ns := $.DNSAddresses }} + - {{$ns}} + {{- end }} + {{- end }} {{- end }} diff --git a/pkg/cidata/cidata.go b/pkg/cidata/cidata.go index 96e66131d53..26c01ff0388 100644 --- a/pkg/cidata/cidata.go +++ b/pkg/cidata/cidata.go @@ -16,6 +16,7 @@ import ( "github.com/lima-vm/lima/pkg/iso9660util" "github.com/lima-vm/lima/pkg/limayaml" "github.com/lima-vm/lima/pkg/localpathutil" + "github.com/lima-vm/lima/pkg/osutil" "github.com/lima-vm/lima/pkg/qemu/qemuconst" "github.com/lima-vm/lima/pkg/sshutil" "github.com/lima-vm/lima/pkg/store/filenames" @@ -51,6 +52,7 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML) error { User: u.Username, UID: uid, Containerd: Containerd{System: *y.Containerd.System, User: *y.Containerd.User}, + SlirpNICName: qemuconst.SlirpNICName, SlirpGateway: qemuconst.SlirpGateway, Env: y.Env, } @@ -80,6 +82,11 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML) error { args.Networks = append(args.Networks, Network{MACAddress: vde.MACAddress, Name: vde.Name}) } + args.DNSAddresses, err = osutil.DNSAddresses() + if err != nil { + return err + } + if err := ValidateTemplateArgs(args); err != nil { return err } diff --git a/pkg/cidata/template.go b/pkg/cidata/template.go index 15925b9fa8d..3976779d53d 100644 --- a/pkg/cidata/template.go +++ b/pkg/cidata/template.go @@ -35,8 +35,10 @@ type TemplateArgs struct { Mounts []string // abs path, accessible by the User Containerd Containerd Networks []Network + SlirpNICName string SlirpGateway string Env map[string]*string + DNSAddresses []string } func ValidateTemplateArgs(args TemplateArgs) error { diff --git a/pkg/osutil/dns_darwin.go b/pkg/osutil/dns_darwin.go new file mode 100644 index 00000000000..f86c00bb41e --- /dev/null +++ b/pkg/osutil/dns_darwin.go @@ -0,0 +1,25 @@ +package osutil + +import "github.com/lima-vm/lima/pkg/sysprof" + +func DNSAddresses() ([]string, error) { + nwData, err := sysprof.NetworkData() + if err != nil { + return nil, err + } + var addresses []string + if len(nwData) > 0 { + // Return DNS addresses from en0 interface + for _, nw := range nwData { + if nw.Interface == "en0" { + addresses = nw.DNS.ServerAddresses + break + } + } + // In case "en0" is not found, use the addresses of the first interface + if len(addresses) == 0 { + addresses = nwData[0].DNS.ServerAddresses + } + } + return addresses, nil +} diff --git a/pkg/osutil/dns_others.go b/pkg/osutil/dns_others.go new file mode 100644 index 00000000000..b4d7b4c7272 --- /dev/null +++ b/pkg/osutil/dns_others.go @@ -0,0 +1,9 @@ +//go:build !darwin +// +build !darwin + +package osutil + +func DNSAddresses() ([]string, error) { + // TODO: parse /etc/resolv.conf? + return []string{}, nil +} diff --git a/pkg/osutil/osutil_others.go b/pkg/osutil/osutil_others.go index c87ed1adf50..ec5eda734aa 100644 --- a/pkg/osutil/osutil_others.go +++ b/pkg/osutil/osutil_others.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package osutil diff --git a/pkg/sysprof/network_darwin.go b/pkg/sysprof/network_darwin.go new file mode 100644 index 00000000000..53831a61252 --- /dev/null +++ b/pkg/sysprof/network_darwin.go @@ -0,0 +1,14 @@ +package sysprof + +type SPNetworkDataType struct { + SPNetworkDataType []NetworkDataType `json:"SPNetworkDataType"` +} + +type NetworkDataType struct { + DNS DNS `json:"DNS"` + Interface string `json:"interface"` +} + +type DNS struct { + ServerAddresses []string `json:"ServerAddresses"` +} diff --git a/pkg/sysprof/sysprof_darwin.go b/pkg/sysprof/sysprof_darwin.go new file mode 100644 index 00000000000..4df5c6a1046 --- /dev/null +++ b/pkg/sysprof/sysprof_darwin.go @@ -0,0 +1,37 @@ +package sysprof + +import ( + "bytes" + "encoding/json" + "fmt" + "os/exec" + "sync" +) + +var ( + networkDataOnce sync.Once + networkDataCached SPNetworkDataType + networkDataError error +) + +func NetworkData() ([]NetworkDataType, error) { + networkDataOnce.Do(func() { + jsonBytes, networkDataError := SystemProfiler("SPNetworkDataType") + if networkDataError == nil { + networkDataError = json.Unmarshal(jsonBytes, &networkDataCached) + } + }) + return networkDataCached.SPNetworkDataType, networkDataError +} + +func SystemProfiler(dataType string) ([]byte, error) { + var stdout, stderr bytes.Buffer + cmd := exec.Command("system_profiler", dataType, "-json") + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return nil, fmt.Errorf("failed to run %v: stdout=%q, stderr=%q: %w", + cmd.Args, stdout.String(), stderr.String(), err) + } + return stdout.Bytes(), nil +}