diff --git a/network.go b/network.go index fdcdccd4..604837ca 100644 --- a/network.go +++ b/network.go @@ -322,6 +322,20 @@ func (v *VirtioNetworkDeviceConfiguration) SetMACAddress(macAddress *MACAddress) C.setNetworkDevicesVZMACAddress(objc.Ptr(v), objc.Ptr(macAddress)) } +// GetMACAddress returns the media access control address of the device. +func (v *VirtioNetworkDeviceConfiguration) GetMACAddress() *MACAddress { + macAddress := &MACAddress{ + pointer: objc.NewPointer( + C.getNetworkDevicesVZMACAddress(objc.Ptr(v)), + ), + } + objc.Retain(macAddress) + objc.SetFinalizer(macAddress, func(self *MACAddress) { + objc.Release(self) + }) + return macAddress +} + func (v *VirtioNetworkDeviceConfiguration) Attachment() NetworkDeviceAttachment { return v.attachment } diff --git a/network_test.go b/network_test.go index 314d927b..c6f270a5 100644 --- a/network_test.go +++ b/network_test.go @@ -1,6 +1,7 @@ package vz_test import ( + "bytes" "net" "testing" @@ -45,3 +46,58 @@ func TestFileHandleNetworkDeviceAttachmentMTU(t *testing.T) { t.Fatalf("want mtu %d but got %d", want, got) } } + +func TestVirtioNetworkDeviceConfigurationGetMACAddress(t *testing.T) { + attachment, err := vz.NewNATNetworkDeviceAttachment() + if err != nil { + t.Fatal(err) + } + config, err := vz.NewVirtioNetworkDeviceConfiguration(attachment) + if err != nil { + t.Fatal(err) + } + + want := net.HardwareAddr{0x02, 0x00, 0x5e, 0x10, 0x00, 0x01} + macAddress, err := vz.NewMACAddress(want) + if err != nil { + t.Fatal(err) + } + config.SetMACAddress(macAddress) + + got := config.GetMACAddress() + if got == nil { + t.Fatal("want MAC address but got nil") + } + if got.String() != want.String() { + t.Fatalf("want MAC address %q but got %q", want, got) + } + if gotHardwareAddr := got.HardwareAddr(); !bytes.Equal(gotHardwareAddr, want) { + t.Fatalf("want hardware address %q but got %q", want, gotHardwareAddr) + } +} + +func TestVirtioNetworkDeviceConfigurationGetDefaultMACAddress(t *testing.T) { + attachment, err := vz.NewNATNetworkDeviceAttachment() + if err != nil { + t.Fatal(err) + } + config, err := vz.NewVirtioNetworkDeviceConfiguration(attachment) + if err != nil { + t.Fatal(err) + } + + got := config.GetMACAddress() + if got == nil { + t.Fatal("want default MAC address but got nil") + } + gotHardwareAddr, err := net.ParseMAC(got.String()) + if err != nil { + t.Fatal(err) + } + if len(gotHardwareAddr) != 6 { + t.Fatalf("want 6-byte MAC address but got %d bytes", len(gotHardwareAddr)) + } + if got.String() != gotHardwareAddr.String() { + t.Fatalf("want colon-separated MAC address but got %q", got) + } +} diff --git a/virtualization_11.h b/virtualization_11.h index 464c69d8..d41dcf55 100644 --- a/virtualization_11.h +++ b/virtualization_11.h @@ -97,6 +97,7 @@ void *newVZNATNetworkDeviceAttachment(void); void *newVZFileHandleNetworkDeviceAttachment(int fileDescriptor, void **error); void *newVZVirtioNetworkDeviceConfiguration(void *attachment); void setNetworkDevicesVZMACAddress(void *config, void *macAddress); +void *getNetworkDevicesVZMACAddress(void *config); void *newVZVirtioEntropyDeviceConfiguration(void); void *newVZVirtioBlockDeviceConfiguration(void *attachment); void *newVZDiskImageStorageDeviceAttachment(const char *diskPath, bool readOnly, void **error); diff --git a/virtualization_11.m b/virtualization_11.m index 28060e0f..bd03c4e9 100644 --- a/virtualization_11.m +++ b/virtualization_11.m @@ -917,6 +917,18 @@ void setNetworkDevicesVZMACAddress(void *config, void *macAddress) RAISE_UNSUPPORTED_MACOS_EXCEPTION(); } +/*! + @abstract The media access control address of the device. + */ +void *getNetworkDevicesVZMACAddress(void *config) +{ + if (@available(macOS 11, *)) { + return [(VZNetworkDeviceConfiguration *)config macAddress]; + } + + RAISE_UNSUPPORTED_MACOS_EXCEPTION(); +} + /*! @abstract The address represented as a string. @discussion