diff options
author | Pablo Mazzini <pmazzini@gmail.com> | 2018-08-22 17:27:18 +0100 |
---|---|---|
committer | insomniac <insomniacslk@users.noreply.github.com> | 2018-08-22 17:27:18 +0100 |
commit | 537f1f937790c0bd7826ec6feb6e99fe7ededf58 (patch) | |
tree | 447b52801d5c831f2ffe3c8b97a01cbf5ea6165f /dhcpv6/option_vendorclass.go | |
parent | 051f4413e8ae8c174024f754d7b21ec13a5460b9 (diff) |
add OptVendorClass (#148)
Diffstat (limited to 'dhcpv6/option_vendorclass.go')
-rw-r--r-- | dhcpv6/option_vendorclass.go | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/dhcpv6/option_vendorclass.go b/dhcpv6/option_vendorclass.go new file mode 100644 index 0000000..b920fa7 --- /dev/null +++ b/dhcpv6/option_vendorclass.go @@ -0,0 +1,81 @@ +package dhcpv6 + +import ( + "encoding/binary" + "errors" + "fmt" + "strings" +) + +// OptVendorClass represents a DHCPv6 Vendor Class option +type OptVendorClass struct { + EnterpriseNumber uint32 + Data [][]byte +} + +// Code returns the option code +func (op *OptVendorClass) Code() OptionCode { + return OptionVendorClass +} + +// ToBytes serializes the option and returns it as a sequence of bytes +func (op *OptVendorClass) ToBytes() []byte { + buf := make([]byte, 8) + binary.BigEndian.PutUint16(buf[0:2], uint16(OptionVendorClass)) + binary.BigEndian.PutUint16(buf[2:4], uint16(op.Length())) + binary.BigEndian.PutUint32(buf[4:8], uint32(op.EnterpriseNumber)) + u16 := make([]byte, 2) + for _, data := range op.Data { + binary.BigEndian.PutUint16(u16, uint16(len(data))) + buf = append(buf, u16...) + buf = append(buf, data...) + } + return buf +} + +// Length returns the option length +func (op *OptVendorClass) Length() int { + ret := 0 + for _, data := range op.Data { + ret += 2 + len(data) + } + return 4 + ret +} + +// String returns a string representation of the VendorClass data +func (op *OptVendorClass) String() string { + vcStrings := make([]string, 0) + for _, data := range op.Data { + vcStrings = append(vcStrings, string(data)) + } + return fmt.Sprintf("OptVendorClass{enterprisenum=%d, data=[%s]}", op.EnterpriseNumber, strings.Join(vcStrings, ", ")) +} + +// ParseOptVendorClass builds an OptVendorClass structure from a sequence of +// bytes. The input data does not include option code and length bytes. +func ParseOptVendorClass(data []byte) (*OptVendorClass, error) { + opt := OptVendorClass{} + if len(data) < 4 { + return nil, fmt.Errorf("Invalid vendor opts data length. Expected at least 4 bytes, got %v", len(data)) + } + opt.EnterpriseNumber = binary.BigEndian.Uint32(data[:4]) + data = data[4:] + for { + if len(data) == 0 { + break + } + if len(data) < 2 { + return nil, errors.New("ParseOptVendorClass: short data: missing length field") + } + vcLen := int(binary.BigEndian.Uint16(data[:2])) + if len(data) < vcLen+2 { + return nil, fmt.Errorf("ParseOptVendorClass: short data: less than %d bytes", vcLen+2) + } + opt.Data = append(opt.Data, data[2:vcLen+2]) + data = data[2+vcLen:] + } + if len(opt.Data) < 1 { + return nil, errors.New("ParseOptVendorClass: at least one vendor class data is required") + } + return &opt, nil +} |