diff --git a/base.go b/base.go index 42c119f..b384634 100644 --- a/base.go +++ b/base.go @@ -23,7 +23,9 @@ const ( ) const ( - SATAMessaging DeviceNodeSubType = 18 + SATAMessaging DeviceNodeSubType = 18 + MacMessagingSubType DeviceNodeSubType = 11 + IPv4MessagingSubType DeviceNodeSubType = 12 ) const EndOfEntireDevicePath DeviceNodeSubType = 0xFF diff --git a/ipv4.go b/ipv4.go new file mode 100644 index 0000000..cdf6612 --- /dev/null +++ b/ipv4.go @@ -0,0 +1,55 @@ +package devicepath + +import ( + "errors" + "fmt" + "strconv" + "strings" +) + +const ipv4Prefix string = "IPv4" + +type Ipv4DevicePath struct { + remoteIP string + protocol string + static bool +} + +func (ip *Ipv4DevicePath) Type() DeviceNodeType { + return MessagingDevicePath +} + +func (ip *Ipv4DevicePath) SubType() DeviceNodeSubType { + return IPv4MessagingSubType +} + +func (ip *Ipv4DevicePath) Bytes() []byte { + return nil +} + +func (ip *Ipv4DevicePath) String() string { + ipType := 0 + if ip.static { + ipType = 1 + } + return fmt.Sprintf("%s(%s,%s,%d)", ipv4Prefix, ip.remoteIP, ip.protocol, ipType) +} + +func (ip *Ipv4DevicePath) ParseString(raw string) error { + if !checkStringFormat(raw, ipv4Prefix, -1) { + return ErrMalformedString + } + args := strings.Split(raw[len(ipv4Prefix)+1:len(raw)-1], ",") + if len(args) != 3 { + return errors.New("unexpected number of arguments") + } + + ip.remoteIP = args[0] + ip.protocol = args[1] + if ipType, err := strconv.Atoi(args[2]); err != nil { + return err + } else { + ip.static = ipType == 1 + } + return nil +} diff --git a/ipv4_test.go b/ipv4_test.go new file mode 100644 index 0000000..974ccd4 --- /dev/null +++ b/ipv4_test.go @@ -0,0 +1,18 @@ +package devicepath_test + +import ( + "testing" + + "git.faercol.me/faercol/devicepath" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseIpv4String(t *testing.T) { + t.Run("OK", func(t *testing.T) { + expected := "IPv4(0.0.0.00.0.0.0,0,0)" + var dev devicepath.Ipv4DevicePath + require.NoError(t, dev.ParseString(expected)) + assert.Equal(t, expected, dev.String()) + }) +} diff --git a/ipv6.go b/ipv6.go new file mode 100644 index 0000000..49e0e7b --- /dev/null +++ b/ipv6.go @@ -0,0 +1,55 @@ +package devicepath + +import ( + "errors" + "fmt" + "strconv" + "strings" +) + +const ipv6Prefix string = "IPv6" + +type Ipv6DevicePath struct { + remoteIP string + protocol string + static bool +} + +func (ip *Ipv6DevicePath) Type() DeviceNodeType { + return MessagingDevicePath +} + +func (ip *Ipv6DevicePath) SubType() DeviceNodeSubType { + return IPv4MessagingSubType +} + +func (ip *Ipv6DevicePath) Bytes() []byte { + return nil +} + +func (ip *Ipv6DevicePath) String() string { + ipType := 0 + if ip.static { + ipType = 1 + } + return fmt.Sprintf("%s(%s,%s,%d)", ipv6Prefix, ip.remoteIP, ip.protocol, ipType) +} + +func (ip *Ipv6DevicePath) ParseString(raw string) error { + if !checkStringFormat(raw, ipv6Prefix, -1) { + return ErrMalformedString + } + args := strings.Split(raw[len(ipv6Prefix)+1:len(raw)-1], ",") + if len(args) != 3 { + return errors.New("unexpected number of arguments") + } + + ip.remoteIP = args[0] + ip.protocol = args[1] + if ipType, err := strconv.Atoi(args[2]); err != nil { + return err + } else { + ip.static = ipType == 1 + } + return nil +} diff --git a/ipv6_test.go b/ipv6_test.go new file mode 100644 index 0000000..9e62d86 --- /dev/null +++ b/ipv6_test.go @@ -0,0 +1,18 @@ +package devicepath_test + +import ( + "testing" + + "git.faercol.me/faercol/devicepath" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseIpv6String(t *testing.T) { + t.Run("OK", func(t *testing.T) { + expected := "IPv6([::]:\u003c-\u003e[::]:,0,0)" + var dev devicepath.Ipv6DevicePath + require.NoError(t, dev.ParseString(expected)) + assert.Equal(t, expected, dev.String()) + }) +} diff --git a/mac.go b/mac.go new file mode 100644 index 0000000..4be5102 --- /dev/null +++ b/mac.go @@ -0,0 +1,53 @@ +package devicepath + +import ( + "encoding/hex" + "errors" + "fmt" + "strconv" + "strings" +) + +const macPrefix string = "MAC" + +type MacDevicePath struct { + addr []byte + ifType uint8 +} + +func (mp *MacDevicePath) Type() DeviceNodeType { + return MessagingDevicePath +} + +func (mp *MacDevicePath) SubType() DeviceNodeSubType { + return MacMessagingSubType +} + +func (mp *MacDevicePath) Bytes() []byte { + return nil +} + +func (mp *MacDevicePath) String() string { + return fmt.Sprintf("%s(%x,%d)", macPrefix, mp.addr, mp.ifType) +} + +func (mp *MacDevicePath) ParseString(raw string) error { + if !checkStringFormat(raw, macPrefix, -1) { + return ErrMalformedString + } + args := strings.Split(raw[len(macPrefix)+1:len(raw)-1], ",") + if len(args) != 2 { + return errors.New("unexpected number of arguments") + } + if mac, err := hex.DecodeString(args[0]); err != nil { + return err + } else { + mp.addr = mac + } + if ifType, err := strconv.Atoi(args[1]); err != nil { + return err + } else { + mp.ifType = uint8(ifType) + } + return nil +} diff --git a/mac_test.go b/mac_test.go new file mode 100644 index 0000000..327b311 --- /dev/null +++ b/mac_test.go @@ -0,0 +1,18 @@ +package devicepath_test + +import ( + "testing" + + "git.faercol.me/faercol/devicepath" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseStringMac(t *testing.T) { + t.Run("OK", func(t *testing.T) { + var macDev devicepath.MacDevicePath + expected := "MAC(3c7c3fc1f935,0)" + require.NoError(t, macDev.ParseString(expected)) + assert.Equal(t, expected, macDev.String()) + }) +} diff --git a/parser.go b/parser.go index 142a495..2e34d80 100644 --- a/parser.go +++ b/parser.go @@ -36,6 +36,8 @@ var prefixTypeAssociation = map[string]nodeGenerator{ pciRootPrefix: func() DevicePathNode { return &PCIRootDevicePath{} }, hdPrefix: func() DevicePathNode { return &HardDriveDevicePath{} }, filePrefix: func() DevicePathNode { return &FileDevicePath{} }, + macPrefix: func() DevicePathNode { return &MacDevicePath{} }, + ipv4Prefix: func() DevicePathNode { return &Ipv4DevicePath{} }, } func Parsenode(raw string) (DevicePathNode, error) {