diff options
author | Owen Mooney <owenmooney@fb.com> | 2018-07-24 10:40:15 -0700 |
---|---|---|
committer | Owen Mooney <owenmooney@fb.com> | 2018-07-24 10:40:15 -0700 |
commit | 6075381c81b9da7afdc55b2577cd999191cb8a73 (patch) | |
tree | 190b58b84964bec3323e9cfee48905e67bc27199 /dhcpv4 | |
parent | c429ef3bbfccd838969930058390d5a0a30aca64 (diff) |
Add support for Bootfile name option
Diffstat (limited to 'dhcpv4')
-rw-r--r-- | dhcpv4/option_bootfile_name.go | 54 | ||||
-rw-r--r-- | dhcpv4/option_bootfile_name_test.go | 60 |
2 files changed, 114 insertions, 0 deletions
diff --git a/dhcpv4/option_bootfile_name.go b/dhcpv4/option_bootfile_name.go new file mode 100644 index 0000000..d7b291b --- /dev/null +++ b/dhcpv4/option_bootfile_name.go @@ -0,0 +1,54 @@ +package dhcpv4 + +import ( + "fmt" +) + +// This option implements the Bootfile name Option. +// https://tools.ietf.org/html/rfc2132 + +// OptBootfileName implements the BootFile Name option +type OptBootfileName struct { + BootfileName []byte +} + +// Code returns the option code +func (op *OptBootfileName) Code() OptionCode { + return OptionBootfileName +} + +// ToBytes serializes the option and returns it as a sequence of bytes +func (op *OptBootfileName) ToBytes() []byte { + return append([]byte{byte(op.Code()), byte(op.Length())}, op.BootfileName...) +} + +// Length returns the option length in bytes +func (op *OptBootfileName) Length() int { + return len(op.BootfileName) +} + +func (op *OptBootfileName) String() string { + return fmt.Sprintf("OptBootfileName{BootfileName=%s}", op.BootfileName) + +} + +// ParseOptBootfileName returns a new OptBootfile from a byte stream or error if any +func ParseOptBootfileName(data []byte) (*OptBootfileName, error) { + if len(data) < 3 { + return nil, ErrShortByteStream + } + code := OptionCode(data[0]) + if code != OptionBootfileName { + return nil, fmt.Errorf("expected code %v, got %v", OptionBootfileName, code) + } + length := int(data[1]) + if length < 1 { + return nil, fmt.Errorf("Bootfile name has invalid length of %d", length) + } + data = data[2:] + if len(data) < length { + return nil, fmt.Errorf("ParseOptBootfileName: short data: %d bytes; want %d", + len(data), length) + } + return &OptBootfileName{BootfileName: data[:length]}, nil +} diff --git a/dhcpv4/option_bootfile_name_test.go b/dhcpv4/option_bootfile_name_test.go new file mode 100644 index 0000000..1f66807 --- /dev/null +++ b/dhcpv4/option_bootfile_name_test.go @@ -0,0 +1,60 @@ +package dhcpv4 + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestOptBootfileNameCode(t *testing.T) { + opt := OptBootfileName{} + require.Equal(t, OptionBootfileName, opt.Code()) +} + +func TestOptBootfileNameToBytes(t *testing.T) { + opt := OptBootfileName{ + BootfileName: []byte("linuxboot"), + } + data := opt.ToBytes() + expected := []byte{ + 67, // OptionBootfileName + 9, // length + 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't', + } + require.Equal(t, expected, data) +} + +func TestParseOptBootfileName(t *testing.T) { + expected := []byte{ + 67, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't', + } + opt, err := ParseOptBootfileName(expected) + require.NoError(t, err) + require.Equal(t, 9, opt.Length()) + require.Equal(t, "linuxboot", string(opt.BootfileName)) +} + +func TestParseOptBootfileNameZeroLength(t *testing.T) { + expected := []byte{ + 67, 0, + } + _, err := ParseOptBootfileName(expected) + require.Error(t, err) +} + +func TestParseOptBootfileNameInvalidLength(t *testing.T) { + expected := []byte{ + 67, 9, 'l', 'i', 'n', 'u', 'x', 'b', + } + _, err := ParseOptBootfileName(expected) + require.Error(t, err) +} + +func TestParseOptBootfileNameShortLength(t *testing.T) { + expected := []byte{ + 67, 4, 'l', 'i', 'n', 'u', 'x', + } + opt, err := ParseOptBootfileName(expected) + require.NoError(t, err) + require.Equal(t, []byte("linu"), opt.BootfileName) +} |