diff options
author | Christopher Koch <c@chrisko.ch> | 2019-01-20 04:47:08 +0000 |
---|---|---|
committer | insomniac <insomniacslk@users.noreply.github.com> | 2019-01-26 23:34:26 +0000 |
commit | 3478513076477d0f19eaeaf441f29949a9f6bc92 (patch) | |
tree | 4d621abff002cef480901a2ef015620472293db3 /dhcpv6/option_vendor_opts.go | |
parent | e62883f5b5683ae2259ad01b7ffbe20671deb6b2 (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.go | 84 |
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 } |