diff options
author | insomniac <insomniacslk@users.noreply.github.com> | 2018-07-25 10:30:20 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-25 10:30:20 +0100 |
commit | b9bd21d7d9cb3fb12761808f11d9a40d9d01558e (patch) | |
tree | a3c5bfdfa218bd09c6b29ea202c9b1aca62b6e99 | |
parent | c429ef3bbfccd838969930058390d5a0a30aca64 (diff) | |
parent | c528a468bd226ac63e45bb4dfb610474fb78b51f (diff) |
Add support for Bootfile name option (#91)
-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..73ea625 --- /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("ParseOptBootfileName: invalid code: %v; want %v", code, OptionBootfileName) + } + length := int(data[1]) + if length < 1 { + return nil, fmt.Errorf("Bootfile name has invalid length of %d", length) + } + bootFileNameData := data[2:] + if len(bootFileNameData) < length { + return nil, fmt.Errorf("ParseOptBootfileName: short data: %d bytes; want %d", + len(bootFileNameData), length) + } + return &OptBootfileName{BootfileName: bootFileNameData[: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) +} |