summaryrefslogtreecommitdiffhomepage
path: root/dhcpv6/option_vendor_opts.go
diff options
context:
space:
mode:
authorChristopher Koch <c@chrisko.ch>2019-01-20 04:47:08 +0000
committerinsomniac <insomniacslk@users.noreply.github.com>2019-01-26 23:34:26 +0000
commit3478513076477d0f19eaeaf441f29949a9f6bc92 (patch)
tree4d621abff002cef480901a2ef015620472293db3 /dhcpv6/option_vendor_opts.go
parente62883f5b5683ae2259ad01b7ffbe20671deb6b2 (diff)
dhcpv6: easier option parsing
- move option parsing to uio buffer library. - move option code and length reading into FromBytes rather than implementing it in each OptionParser.
Diffstat (limited to 'dhcpv6/option_vendor_opts.go')
-rw-r--r--dhcpv6/option_vendor_opts.go84
1 files changed, 18 insertions, 66 deletions
diff --git a/dhcpv6/option_vendor_opts.go b/dhcpv6/option_vendor_opts.go
index f791ddf..027e7c3 100644
--- a/dhcpv6/option_vendor_opts.go
+++ b/dhcpv6/option_vendor_opts.go
@@ -1,39 +1,15 @@
package dhcpv6
-/*
- This module defines the OptVendorOpts structure.
- https://tools.ietf.org/html/rfc3315#section-22.17
-
- Option 17
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | OPTION_VENDOR_OPTS | option-len |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | enterprise-number |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- . .
- . option-data (sub-options) .
- . .
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Sub-Option
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | opt-code | option-len |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- . .
- . option-data .
- . .
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-*/
-
import (
- "encoding/binary"
- "errors"
"fmt"
+
+ "github.com/u-root/u-root/pkg/uio"
)
// OptVendorOpts represents a DHCPv6 Status Code option
+//
+// This module defines the OptVendorOpts structure.
+// https://tools.ietf.org/html/rfc3315#section-22.17
type OptVendorOpts struct {
EnterpriseNumber uint32
VendorOpts Options
@@ -46,14 +22,12 @@ func (op *OptVendorOpts) Code() OptionCode {
// ToBytes serializes the option and returns it as a sequence of bytes
func (op *OptVendorOpts) ToBytes() []byte {
- buf := make([]byte, 8)
- binary.BigEndian.PutUint16(buf[0:2], uint16(OptionVendorOpts))
- binary.BigEndian.PutUint16(buf[2:4], uint16(op.Length()))
- binary.BigEndian.PutUint32(buf[4:8], uint32(op.EnterpriseNumber))
- for _, opt := range op.VendorOpts {
- buf = append(buf, opt.ToBytes()...)
- }
- return buf
+ buf := uio.NewBigEndianBuffer(nil)
+ buf.Write16(uint16(OptionVendorOpts))
+ buf.Write16(uint16(op.Length()))
+ buf.Write32(uint32(op.EnterpriseNumber))
+ buf.WriteData(op.VendorOpts.ToBytes())
+ return buf.Data()
}
// Length returns the option length
@@ -75,41 +49,19 @@ func (op *OptVendorOpts) String() string {
// ParseOptVendorOpts builds an OptVendorOpts structure from a sequence of bytes.
// The input data does not include option code and length bytes.
func ParseOptVendorOpts(data []byte) (*OptVendorOpts, error) {
- opt := OptVendorOpts{}
- 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])
-
- if err := opt.VendorOpts.FromBytesWithParser(data[4:], vendParseOption); err != nil {
+ var opt OptVendorOpts
+ buf := uio.NewBigEndianBuffer(data)
+ opt.EnterpriseNumber = buf.Read32()
+ if err := opt.VendorOpts.FromBytesWithParser(buf.ReadAll(), vendParseOption); err != nil {
return nil, err
}
- return &opt, nil
+ return &opt, buf.FinError()
}
// vendParseOption builds a GenericOption from a slice of bytes
// We cannot use the existing ParseOption function in options.go because the
// sub-options include codes specific to each vendor. There are overlaps in these
// codes with RFC standard codes.
-func vendParseOption(dataStart []byte) (Option, error) {
- // Parse a sequence of bytes as a single DHCPv6 option.
- // Returns the option structure, or an error if any.
-
- if len(dataStart) < 4 {
- return nil, fmt.Errorf("Invalid DHCPv6 vendor option: less than 4 bytes")
- }
- code := OptionCode(binary.BigEndian.Uint16(dataStart[:2]))
- length := int(binary.BigEndian.Uint16(dataStart[2:4]))
- if len(dataStart) < length+4 {
- return nil, fmt.Errorf("Invalid option length for vendor option %v. Declared %v, actual %v",
- code, length, len(dataStart)-4,
- )
- }
-
- optData := dataStart[4 : 4+length]
- if len(optData) < 1 {
- return nil, errors.New("vendParseOption: at least one vendor options data is required")
- }
-
- return &OptionGeneric{OptionCode: code, OptionData: optData}, nil
+func vendParseOption(code OptionCode, data []byte) (Option, error) {
+ return &OptionGeneric{OptionCode: code, OptionData: data}, nil
}