summaryrefslogtreecommitdiffhomepage
path: root/dhcpv6/option_vendorclass.go
diff options
context:
space:
mode:
authorPablo Mazzini <pmazzini@gmail.com>2018-08-22 17:27:18 +0100
committerinsomniac <insomniacslk@users.noreply.github.com>2018-08-22 17:27:18 +0100
commit537f1f937790c0bd7826ec6feb6e99fe7ededf58 (patch)
tree447b52801d5c831f2ffe3c8b97a01cbf5ea6165f /dhcpv6/option_vendorclass.go
parent051f4413e8ae8c174024f754d7b21ec13a5460b9 (diff)
add OptVendorClass (#148)
Diffstat (limited to 'dhcpv6/option_vendorclass.go')
-rw-r--r--dhcpv6/option_vendorclass.go81
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
+}