diff options
author | Chris Koch <chrisko@google.com> | 2023-02-18 20:31:32 -0800 |
---|---|---|
committer | Chris K <c@chrisko.ch> | 2023-02-19 22:39:16 -0800 |
commit | 336d4b9bd652b2bf0bc1bd0feae3f2f51009c13f (patch) | |
tree | 9c99ebb8f3067a39981d8bea07109fd7e7ba0d17 | |
parent | 1e0fe5ce427973ca92a0dfb1a06a252ddb0dd4be (diff) |
dhcpv6: convert every Parse function to FromBytes
Signed-off-by: Chris Koch <chrisko@google.com>
55 files changed, 415 insertions, 331 deletions
diff --git a/dhcpv6/dhcpv6message.go b/dhcpv6/dhcpv6message.go index 8886c6c..45fa5f1 100644 --- a/dhcpv6/dhcpv6message.go +++ b/dhcpv6/dhcpv6message.go @@ -169,8 +169,8 @@ func (mo MessageOptions) BootFileURL() string { if opt == nil { return "" } - if u, ok := opt.(optBootFileURL); ok { - return string(u) + if u, ok := opt.(*optBootFileURL); ok { + return u.url } return "" } @@ -181,8 +181,8 @@ func (mo MessageOptions) BootFileParam() []string { if opt == nil { return nil } - if u, ok := opt.(optBootFileParam); ok { - return []string(u) + if u, ok := opt.(*optBootFileParam); ok { + return u.params } return nil } diff --git a/dhcpv6/option_archtype.go b/dhcpv6/option_archtype.go index a5514cd..2b778d8 100644 --- a/dhcpv6/option_archtype.go +++ b/dhcpv6/option_archtype.go @@ -26,10 +26,6 @@ func (op optClientArchType) String() string { return fmt.Sprintf("%s: %s", op.Code(), op.Archs) } -// parseOptClientArchType builds an OptClientArchType structure from -// a sequence of bytes The input data does not include option code and -// length bytes. -func parseOptClientArchType(data []byte) (*optClientArchType, error) { - var opt optClientArchType - return &opt, opt.FromBytes(data) +func (op *optClientArchType) FromBytes(p []byte) error { + return op.Archs.FromBytes(p) } diff --git a/dhcpv6/option_archtype_test.go b/dhcpv6/option_archtype_test.go index 0481c1a..8ebd18f 100644 --- a/dhcpv6/option_archtype_test.go +++ b/dhcpv6/option_archtype_test.go @@ -11,14 +11,16 @@ func TestParseOptClientArchType(t *testing.T) { data := []byte{ 0, 6, // EFI_IA32 } - opt, err := parseOptClientArchType(data) + var opt optClientArchType + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, iana.EFI_IA32, opt.Archs[0]) } func TestParseOptClientArchTypeInvalid(t *testing.T) { data := []byte{42} - _, err := parseOptClientArchType(data) + var opt optClientArchType + err := opt.FromBytes(data) require.Error(t, err) } @@ -26,7 +28,8 @@ func TestOptClientArchTypeParseAndToBytes(t *testing.T) { data := []byte{ 0, 8, // EFI_XSCALE } - opt, err := parseOptClientArchType(data) + var opt optClientArchType + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, data, opt.ToBytes()) } diff --git a/dhcpv6/option_bootfileparam.go b/dhcpv6/option_bootfileparam.go index 7618080..ba09ca0 100644 --- a/dhcpv6/option_bootfileparam.go +++ b/dhcpv6/option_bootfileparam.go @@ -9,10 +9,12 @@ import ( // OptBootFileParam returns a BootfileParam option as defined in RFC 5970 // Section 3.2. func OptBootFileParam(args ...string) Option { - return optBootFileParam(args) + return &optBootFileParam{args} } -type optBootFileParam []string +type optBootFileParam struct { + params []string +} // Code returns the option code func (optBootFileParam) Code() OptionCode { @@ -22,7 +24,7 @@ func (optBootFileParam) Code() OptionCode { // ToBytes serializes the option and returns it as a sequence of bytes func (op optBootFileParam) ToBytes() []byte { buf := uio.NewBigEndianBuffer(nil) - for _, param := range op { + for _, param := range op.params { if len(param) >= 1<<16 { // TODO: say something here instead of silently ignoring a parameter continue @@ -42,20 +44,16 @@ func (op optBootFileParam) ToBytes() []byte { } func (op optBootFileParam) String() string { - return fmt.Sprintf("%s: %v", op.Code(), ([]string)(op)) + return fmt.Sprintf("%s: %v", op.Code(), op.params) } -// parseOptBootFileParam builds an OptBootFileParam structure from a sequence +// FromBytes builds an OptBootFileParam structure from a sequence // of bytes. The input data does not include option code and length bytes. -func parseOptBootFileParam(data []byte) (optBootFileParam, error) { +func (op *optBootFileParam) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - var result optBootFileParam for buf.Has(2) { length := buf.Read16() - result = append(result, string(buf.CopyN(int(length)))) - } - if err := buf.FinError(); err != nil { - return nil, err + op.params = append(op.params, string(buf.CopyN(int(length)))) } - return result, nil + return buf.FinError() } diff --git a/dhcpv6/option_bootfileparam_test.go b/dhcpv6/option_bootfileparam_test.go index 467f245..3bc266d 100644 --- a/dhcpv6/option_bootfileparam_test.go +++ b/dhcpv6/option_bootfileparam_test.go @@ -41,8 +41,8 @@ func compileTestBootfileParams(t *testing.T, params []string) []byte { func TestOptBootFileParam(t *testing.T) { expected := string(compileTestBootfileParams(t, testBootfileParams1)) - opt, err := parseOptBootFileParam([]byte(expected)) - if err != nil { + var opt optBootFileParam + if err := opt.FromBytes([]byte(expected)); err != nil { t.Fatal(err) } if string(opt.ToBytes()) != expected { @@ -54,10 +54,10 @@ func TestParsedTypeOptBootFileParam(t *testing.T) { tryParse := func(compiled []byte, expected []string) { opt, err := ParseOption(OptionBootfileParam, compiled) require.NoError(t, err) - bootfileParamOpt, ok := opt.(optBootFileParam) + bootfileParamOpt, ok := opt.(*optBootFileParam) require.True(t, ok, fmt.Sprintf("invalid type: %T instead of %T", opt, bootfileParamOpt)) require.Equal(t, compiled, bootfileParamOpt.ToBytes()) - require.Equal(t, expected, ([]string)(bootfileParamOpt)) + require.Equal(t, expected, bootfileParamOpt.params) } tryParse( diff --git a/dhcpv6/option_bootfileurl.go b/dhcpv6/option_bootfileurl.go index 1461189..7a8e54a 100644 --- a/dhcpv6/option_bootfileurl.go +++ b/dhcpv6/option_bootfileurl.go @@ -6,10 +6,12 @@ import ( // OptBootFileURL returns a OptionBootfileURL as defined by RFC 5970. func OptBootFileURL(url string) Option { - return optBootFileURL(url) + return &optBootFileURL{url} } -type optBootFileURL string +type optBootFileURL struct { + url string +} // Code returns the option code func (op optBootFileURL) Code() OptionCode { @@ -18,15 +20,16 @@ func (op optBootFileURL) Code() OptionCode { // ToBytes serializes the option and returns it as a sequence of bytes func (op optBootFileURL) ToBytes() []byte { - return []byte(op) + return []byte(op.url) } func (op optBootFileURL) String() string { - return fmt.Sprintf("%s: %s", op.Code(), string(op)) + return fmt.Sprintf("%s: %s", op.Code(), op.url) } -// parseOptBootFileURL builds an optBootFileURL structure from a sequence +// FromBytes builds an optBootFileURL structure from a sequence // of bytes. The input data does not include option code and length bytes. -func parseOptBootFileURL(data []byte) (optBootFileURL, error) { - return optBootFileURL(string(data)), nil +func (op *optBootFileURL) FromBytes(data []byte) error { + op.url = string(data) + return nil } diff --git a/dhcpv6/option_bootfileurl_test.go b/dhcpv6/option_bootfileurl_test.go index ac45ef5..b65d644 100644 --- a/dhcpv6/option_bootfileurl_test.go +++ b/dhcpv6/option_bootfileurl_test.go @@ -9,11 +9,11 @@ import ( func TestOptBootFileURL(t *testing.T) { expected := "https://insomniac.slackware.it" - opt, err := parseOptBootFileURL([]byte(expected)) - if err != nil { + var opt optBootFileURL + if err := opt.FromBytes([]byte(expected)); err != nil { t.Fatal(err) } - if string(opt) != expected { + if opt.url != expected { t.Fatalf("Invalid boot file URL. Expected %v, got %v", expected, opt) } require.Contains(t, opt.String(), "https://insomniac.slackware.it", "String() should contain the correct BootFileUrl output") diff --git a/dhcpv6/option_clientid.go b/dhcpv6/option_clientid.go index d07c4d5..eea0d01 100644 --- a/dhcpv6/option_clientid.go +++ b/dhcpv6/option_clientid.go @@ -22,13 +22,11 @@ func (op *optClientID) String() string { return fmt.Sprintf("%s: %s", op.Code(), op.DUID) } -// parseOptClientID builds an OptClientId structure from a sequence +// FromBytes builds an optClientID structure from a sequence // of bytes. The input data does not include option code and length // bytes. -func parseOptClientID(data []byte) (*optClientID, error) { - cid, err := DUIDFromBytes(data) - if err != nil { - return nil, err - } - return &optClientID{cid}, nil +func (op *optClientID) FromBytes(data []byte) error { + var err error + op.DUID, err = DUIDFromBytes(data) + return err } diff --git a/dhcpv6/option_clientid_test.go b/dhcpv6/option_clientid_test.go index 0bac410..84e87d9 100644 --- a/dhcpv6/option_clientid_test.go +++ b/dhcpv6/option_clientid_test.go @@ -14,7 +14,8 @@ func TestParseOptClientID(t *testing.T) { 0, 1, // hwtype ethernet 0, 1, 2, 3, 4, 5, // hw addr } - opt, err := parseOptClientID(data) + var opt optClientID + err := opt.FromBytes(data) require.NoError(t, err) want := OptClientID( &DUIDLL{ @@ -22,7 +23,7 @@ func TestParseOptClientID(t *testing.T) { LinkLayerAddr: net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5}), }, ) - require.Equal(t, want, opt) + require.Equal(t, want, &opt) } func TestOptClientIdToBytes(t *testing.T) { @@ -46,7 +47,8 @@ func TestOptClientIdDecodeEncode(t *testing.T) { 0, 1, // hwtype ethernet 5, 4, 3, 2, 1, 0, // hw addr } - opt, err := parseOptClientID(data) + var opt optClientID + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, data, opt.ToBytes()) } @@ -73,7 +75,8 @@ func TestOptClientIdparseOptClientIDBogusDUID(t *testing.T) { 1, 2, 3, 4, 5, 6, 7, 8, 9, // a UUID should be 18 bytes not 17 10, 11, 12, 13, 14, 15, 16, 17, } - _, err := parseOptClientID(data) + var opt optClientID + err := opt.FromBytes(data) require.Error(t, err, "A truncated OptClientId DUID should return an error") } @@ -81,6 +84,7 @@ func TestOptClientIdparseOptClientIDInvalidTooShort(t *testing.T) { data := []byte{ 0, // truncated: DUIDs are at least 2 bytes } - _, err := parseOptClientID(data) + var opt optClientID + err := opt.FromBytes(data) require.Error(t, err, "A truncated OptClientId should return an error") } diff --git a/dhcpv6/option_clientlinklayeraddress.go b/dhcpv6/option_clientlinklayeraddress.go index d5ec028..878a576 100644 --- a/dhcpv6/option_clientlinklayeraddress.go +++ b/dhcpv6/option_clientlinklayeraddress.go @@ -36,12 +36,11 @@ func (op *optClientLinkLayerAddress) String() string { return fmt.Sprintf("%s: Type=%s LinkLayerAddress=%s", op.Code(), op.LinkLayerType, op.LinkLayerAddress) } -// parseOptClientLinkLayerAddress deserializes from bytes -// to build an optClientLinkLayerAddress structure. -func parseOptClientLinkLayerAddress(data []byte) (*optClientLinkLayerAddress, error) { - var opt optClientLinkLayerAddress +// FromBytes deserializes from bytes to build an optClientLinkLayerAddress +// structure. +func (op *optClientLinkLayerAddress) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - opt.LinkLayerType = iana.HWType(buf.Read16()) - opt.LinkLayerAddress = buf.ReadAll() - return &opt, buf.FinError() + op.LinkLayerType = iana.HWType(buf.Read16()) + op.LinkLayerAddress = buf.ReadAll() + return buf.FinError() } diff --git a/dhcpv6/option_clientlinklayeraddress_test.go b/dhcpv6/option_clientlinklayeraddress_test.go index 9e243a4..1ef40c5 100644 --- a/dhcpv6/option_clientlinklayeraddress_test.go +++ b/dhcpv6/option_clientlinklayeraddress_test.go @@ -14,7 +14,8 @@ func TestParseOptClientLinkLayerAddress(t *testing.T) { 0, 1, // LinkLayerType 164, 131, 231, 227, 223, 136, } - opt, err := parseOptClientLinkLayerAddress(data) + var opt optClientLinkLayerAddress + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, OptionClientLinkLayerAddr, opt.Code()) diff --git a/dhcpv6/option_dhcpv4_msg.go b/dhcpv6/option_dhcpv4_msg.go index ad29353..825ea8a 100644 --- a/dhcpv6/option_dhcpv4_msg.go +++ b/dhcpv6/option_dhcpv4_msg.go @@ -40,12 +40,10 @@ func (op *OptDHCPv4Msg) LongString(indent int) string { return fmt.Sprintf("%s: {%v%s}", op.Code(), summary, ind) } -// ParseOptDHCPv4Msg builds an OptDHCPv4Msg structure -// from a sequence of bytes. The input data does not include option code and length -// bytes. -func ParseOptDHCPv4Msg(data []byte) (*OptDHCPv4Msg, error) { - var opt OptDHCPv4Msg +// FromBytes builds an OptDHCPv4Msg structure from a sequence of bytes. The +// input data does not include option code and length bytes. +func (op *OptDHCPv4Msg) FromBytes(data []byte) error { var err error - opt.Msg, err = dhcpv4.FromBytes(data) - return &opt, err + op.Msg, err = dhcpv4.FromBytes(data) + return err } diff --git a/dhcpv6/option_dhcpv4_msg_test.go b/dhcpv6/option_dhcpv4_msg_test.go index d8d3f6d..e7bb1f6 100644 --- a/dhcpv6/option_dhcpv4_msg_test.go +++ b/dhcpv6/option_dhcpv4_msg_test.go @@ -43,7 +43,8 @@ func TestParseOptDHCPv4Msg(t *testing.T) { // magic cookie, then no options data = append(data, magicCookie[:]...) - opt, err := ParseOptDHCPv4Msg(data) + var opt OptDHCPv4Msg + err := opt.FromBytes(data) d := opt.Msg require.NoError(t, err) require.Equal(t, d.OpCode, dhcpv4.OpcodeBootRequest) diff --git a/dhcpv6/option_dhcpv4_o_dhcpv6_server.go b/dhcpv6/option_dhcpv4_o_dhcpv6_server.go index f1f2d27..1bd60af 100644 --- a/dhcpv6/option_dhcpv4_o_dhcpv6_server.go +++ b/dhcpv6/option_dhcpv4_o_dhcpv6_server.go @@ -33,14 +33,12 @@ func (op *OptDHCP4oDHCP6Server) String() string { return fmt.Sprintf("%s: %v", op.Code(), op.DHCP4oDHCP6Servers) } -// ParseOptDHCP4oDHCP6Server builds an OptDHCP4oDHCP6Server structure -// from a sequence of bytes. The input data does not include option code and length -// bytes. -func ParseOptDHCP4oDHCP6Server(data []byte) (*OptDHCP4oDHCP6Server, error) { - var opt OptDHCP4oDHCP6Server +// FromBytes builds an OptDHCP4oDHCP6Server structure from a sequence of bytes. +// The input data does not include option code and length bytes. +func (op *OptDHCP4oDHCP6Server) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) for buf.Has(net.IPv6len) { - opt.DHCP4oDHCP6Servers = append(opt.DHCP4oDHCP6Servers, buf.CopyN(net.IPv6len)) + op.DHCP4oDHCP6Servers = append(op.DHCP4oDHCP6Servers, buf.CopyN(net.IPv6len)) } - return &opt, buf.FinError() + return buf.FinError() } diff --git a/dhcpv6/option_dhcpv4_o_dhcpv6_server_test.go b/dhcpv6/option_dhcpv4_o_dhcpv6_server_test.go index ae5bcdc..85d48e2 100644 --- a/dhcpv6/option_dhcpv4_o_dhcpv6_server_test.go +++ b/dhcpv6/option_dhcpv4_o_dhcpv6_server_test.go @@ -14,7 +14,8 @@ func TestParseOptDHCP4oDHCP6Server(t *testing.T) { expected := []net.IP{ net.IP(data), } - opt, err := ParseOptDHCP4oDHCP6Server(data) + var opt OptDHCP4oDHCP6Server + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, expected, opt.DHCP4oDHCP6Servers) require.Equal(t, OptionDHCP4oDHCP6Server, opt.Code()) @@ -34,7 +35,8 @@ func TestOptDHCP4oDHCP6ServerToBytes(t *testing.T) { func TestParseOptDHCP4oDHCP6ServerParseNoAddr(t *testing.T) { data := []byte{} var expected []net.IP - opt, err := ParseOptDHCP4oDHCP6Server(data) + var opt OptDHCP4oDHCP6Server + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, expected, opt.DHCP4oDHCP6Servers) } @@ -49,6 +51,7 @@ func TestParseOptDHCP4oDHCP6ServerParseBogus(t *testing.T) { data := []byte{ 0x2a, 0x03, 0x28, 0x80, 0xff, 0xfe, 0x00, 0x0c, // invalid IPv6 address } - _, err := ParseOptDHCP4oDHCP6Server(data) + var opt OptDHCP4oDHCP6Server + err := opt.FromBytes(data) require.Error(t, err, "An invalid IPv6 address should return an error") } diff --git a/dhcpv6/option_dns.go b/dhcpv6/option_dns.go index f69973a..af9bafe 100644 --- a/dhcpv6/option_dns.go +++ b/dhcpv6/option_dns.go @@ -34,14 +34,12 @@ func (op *optDNS) String() string { return fmt.Sprintf("%s: %v", op.Code(), op.NameServers) } -// parseOptDNS builds an optDNS structure -// from a sequence of bytes. The input data does not include option code and length -// bytes. -func parseOptDNS(data []byte) (*optDNS, error) { - var opt optDNS +// FromBytes builds an optDNS structure from a sequence of bytes. The input +// data does not include option code and length bytes. +func (op *optDNS) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) for buf.Has(net.IPv6len) { - opt.NameServers = append(opt.NameServers, buf.CopyN(net.IPv6len)) + op.NameServers = append(op.NameServers, buf.CopyN(net.IPv6len)) } - return &opt, buf.FinError() + return buf.FinError() } diff --git a/dhcpv6/option_dns_test.go b/dhcpv6/option_dns_test.go index 34f22f7..2c81076 100644 --- a/dhcpv6/option_dns_test.go +++ b/dhcpv6/option_dns_test.go @@ -14,7 +14,8 @@ func TestParseOptDNS(t *testing.T) { expected := []net.IP{ net.IP(data), } - opt, err := parseOptDNS(data) + var opt optDNS + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, expected, opt.NameServers) require.Equal(t, OptionDNSRecursiveNameServer, opt.Code()) @@ -35,6 +36,7 @@ func TestParseOptDNSBogus(t *testing.T) { data := []byte{ 0x2a, 0x03, 0x28, 0x80, 0xff, 0xfe, 0x00, 0x0c, // invalid IPv6 address } - _, err := parseOptDNS(data) + var opt optDNS + err := opt.FromBytes(data) require.Error(t, err, "An invalid nameserver IPv6 address should return an error") } diff --git a/dhcpv6/option_domainsearchlist.go b/dhcpv6/option_domainsearchlist.go index e94799d..fd8aa01 100644 --- a/dhcpv6/option_domainsearchlist.go +++ b/dhcpv6/option_domainsearchlist.go @@ -28,14 +28,10 @@ func (op *optDomainSearchList) String() string { return fmt.Sprintf("%s: %s", op.Code(), op.DomainSearchList) } -// ParseOptDomainSearchList builds an OptDomainSearchList structure from a sequence -// of bytes. The input data does not include option code and length bytes. -func parseOptDomainSearchList(data []byte) (*optDomainSearchList, error) { - var opt optDomainSearchList +// FromBytes builds an OptDomainSearchList structure from a sequence of bytes. +// The input data does not include option code and length bytes. +func (op *optDomainSearchList) FromBytes(data []byte) error { var err error - opt.DomainSearchList, err = rfc1035label.FromBytes(data) - if err != nil { - return nil, err - } - return &opt, nil + op.DomainSearchList, err = rfc1035label.FromBytes(data) + return err } diff --git a/dhcpv6/option_domainsearchlist_test.go b/dhcpv6/option_domainsearchlist_test.go index 433f710..c03759c 100644 --- a/dhcpv6/option_domainsearchlist_test.go +++ b/dhcpv6/option_domainsearchlist_test.go @@ -12,7 +12,8 @@ func TestParseOptDomainSearchList(t *testing.T) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0, 6, 's', 'u', 'b', 'n', 'e', 't', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'o', 'r', 'g', 0, } - opt, err := parseOptDomainSearchList(data) + var opt optDomainSearchList + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, OptionDomainSearchList, opt.Code()) require.Equal(t, 2, len(opt.DomainSearchList.Labels)) @@ -42,6 +43,7 @@ func TestParseOptDomainSearchListInvalidLength(t *testing.T) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0, 6, 's', 'u', 'b', 'n', 'e', 't', 7, 'e', // truncated } - _, err := parseOptDomainSearchList(data) + var opt optDomainSearchList + err := opt.FromBytes(data) require.Error(t, err, "A truncated OptDomainSearchList should return an error") } diff --git a/dhcpv6/option_elapsedtime.go b/dhcpv6/option_elapsedtime.go index 823c942..1441428 100644 --- a/dhcpv6/option_elapsedtime.go +++ b/dhcpv6/option_elapsedtime.go @@ -32,11 +32,10 @@ func (op *optElapsedTime) String() string { return fmt.Sprintf("%s: %s", op.Code(), op.ElapsedTime) } -// build an optElapsedTime structure from a sequence of bytes. +// FromBytes builds an optElapsedTime structure from a sequence of bytes. // The input data does not include option code and length bytes. -func parseOptElapsedTime(data []byte) (*optElapsedTime, error) { - var opt optElapsedTime +func (op *optElapsedTime) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - opt.ElapsedTime = time.Duration(buf.Read16()) * 10 * time.Millisecond - return &opt, buf.FinError() + op.ElapsedTime = time.Duration(buf.Read16()) * 10 * time.Millisecond + return buf.FinError() } diff --git a/dhcpv6/option_elapsedtime_test.go b/dhcpv6/option_elapsedtime_test.go index 2155539..b0d2dc1 100644 --- a/dhcpv6/option_elapsedtime_test.go +++ b/dhcpv6/option_elapsedtime_test.go @@ -9,7 +9,8 @@ import ( ) func TestOptElapsedTime(t *testing.T) { - opt, err := parseOptElapsedTime([]byte{0xaa, 0xbb}) + var opt optElapsedTime + err := opt.FromBytes([]byte{0xaa, 0xbb}) if err != nil { t.Fatal(err) } @@ -35,9 +36,10 @@ func TestOptElapsedTimeString(t *testing.T) { } func TestOptElapsedTimeParseInvalidOption(t *testing.T) { - _, err := parseOptElapsedTime([]byte{0xaa}) + var opt optElapsedTime + err := opt.FromBytes([]byte{0xaa}) require.Error(t, err, "A short option should return an error") - _, err = parseOptElapsedTime([]byte{0xaa, 0xbb, 0xcc}) + err = opt.FromBytes([]byte{0xaa, 0xbb, 0xcc}) require.Error(t, err, "An option with too many bytes should return an error") } diff --git a/dhcpv6/option_fqdn.go b/dhcpv6/option_fqdn.go index 73a525a..adb47fb 100644 --- a/dhcpv6/option_fqdn.go +++ b/dhcpv6/option_fqdn.go @@ -32,15 +32,14 @@ func (op *OptFQDN) String() string { return fmt.Sprintf("%s: {Flags=%d DomainName=%s}", op.Code(), op.Flags, op.DomainName) } -// ParseOptFQDN deserializes from bytes to build a OptFQDN structure. -func ParseOptFQDN(data []byte) (*OptFQDN, error) { - var opt OptFQDN +// FromBytes deserializes from bytes to build a OptFQDN structure. +func (op *OptFQDN) FromBytes(data []byte) error { var err error buf := uio.NewBigEndianBuffer(data) - opt.Flags = buf.Read8() - opt.DomainName, err = rfc1035label.FromBytes(buf.ReadAll()) + op.Flags = buf.Read8() + op.DomainName, err = rfc1035label.FromBytes(buf.ReadAll()) if err != nil { - return nil, err + return err } - return &opt, buf.FinError() + return buf.FinError() } diff --git a/dhcpv6/option_fqdn_test.go b/dhcpv6/option_fqdn_test.go index 69720ba..0bb2ab4 100644 --- a/dhcpv6/option_fqdn_test.go +++ b/dhcpv6/option_fqdn_test.go @@ -14,7 +14,8 @@ func TestParseOptFQDN(t *testing.T) { 4, 'c', 'n', 'o', 's', 9, 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', 0, } - opt, err := ParseOptFQDN(data) + var opt OptFQDN + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, OptionFQDN, opt.Code()) diff --git a/dhcpv6/option_iaaddress.go b/dhcpv6/option_iaaddress.go index 072ba65..bc56254 100644 --- a/dhcpv6/option_iaaddress.go +++ b/dhcpv6/option_iaaddress.go @@ -69,22 +69,20 @@ func (op *OptIAAddress) LongString(indent int) string { op.Code(), op.IPv6Addr, op.PreferredLifetime, op.ValidLifetime, op.Options.LongString(indent)) } -// ParseOptIAAddress builds an OptIAAddress structure from a sequence -// of bytes. The input data does not include option code and length -// bytes. -func ParseOptIAAddress(data []byte) (*OptIAAddress, error) { - var opt OptIAAddress +// FromBytes builds an OptIAAddress structure from a sequence of bytes. The +// input data does not include option code and length bytes. +func (op *OptIAAddress) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - opt.IPv6Addr = net.IP(buf.CopyN(net.IPv6len)) + op.IPv6Addr = net.IP(buf.CopyN(net.IPv6len)) var t1, t2 Duration t1.Unmarshal(buf) t2.Unmarshal(buf) - opt.PreferredLifetime = t1.Duration - opt.ValidLifetime = t2.Duration + op.PreferredLifetime = t1.Duration + op.ValidLifetime = t2.Duration - if err := opt.Options.FromBytes(buf.ReadAll()); err != nil { - return nil, err + if err := op.Options.FromBytes(buf.ReadAll()); err != nil { + return err } - return &opt, buf.FinError() + return buf.FinError() } diff --git a/dhcpv6/option_iaaddress_test.go b/dhcpv6/option_iaaddress_test.go index 26f1732..2f3db50 100644 --- a/dhcpv6/option_iaaddress_test.go +++ b/dhcpv6/option_iaaddress_test.go @@ -15,7 +15,8 @@ func TestOptIAAddressParse(t *testing.T) { 0xe, 0xf, 0x1, 0x2, // valid lifetime 0, 8, 0, 2, 0xaa, 0xbb, // options }...) - opt, err := ParseOptIAAddress(data) + var opt OptIAAddress + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, net.IP(ipaddr), opt.IPv6Addr) require.Equal(t, 0x0a0b0c0d*time.Second, opt.PreferredLifetime) @@ -28,7 +29,8 @@ func TestOptIAAddressParseInvalidTooShort(t *testing.T) { 0xa, 0xb, 0xc, 0xd, // preferred lifetime // truncated here } - _, err := ParseOptIAAddress(data) + var opt OptIAAddress + err := opt.FromBytes(data) require.Error(t, err) } @@ -39,7 +41,8 @@ func TestOptIAAddressParseInvalidBrokenOptions(t *testing.T) { 0xe, 0xf, 0x1, 0x2, // valid lifetime 0, 8, 0, 2, 0xaa, // broken options } - _, err := ParseOptIAAddress(data) + var opt OptIAAddress + err := opt.FromBytes(data) require.Error(t, err) } @@ -78,7 +81,8 @@ func TestOptIAAddressString(t *testing.T) { 0x00, 0x00, 0x00, 50, // valid lifetime 0, 8, 0, 2, 0xaa, 0xbb, // options }...) - opt, err := ParseOptIAAddress(data) + var opt OptIAAddress + err := opt.FromBytes(data) require.NoError(t, err) str := opt.String() diff --git a/dhcpv6/option_iapd.go b/dhcpv6/option_iapd.go index 6296103..d853cea 100644 --- a/dhcpv6/option_iapd.go +++ b/dhcpv6/option_iapd.go @@ -79,21 +79,20 @@ func (op *OptIAPD) LongString(indentSpace int) string { return fmt.Sprintf("%s: IAID=%#x T1=%v T2=%v Options=%v", op.Code(), op.IaId, op.T1, op.T2, op.Options.LongString(indentSpace)) } -// ParseOptIAPD builds an OptIAPD structure from a sequence of bytes. -// The input data does not include option code and length bytes. -func ParseOptIAPD(data []byte) (*OptIAPD, error) { - var opt OptIAPD +// FromBytes builds an OptIAPD structure from a sequence of bytes. The input +// data does not include option code and length bytes. +func (op *OptIAPD) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - buf.ReadBytes(opt.IaId[:]) + buf.ReadBytes(op.IaId[:]) var t1, t2 Duration t1.Unmarshal(buf) t2.Unmarshal(buf) - opt.T1 = t1.Duration - opt.T2 = t2.Duration + op.T1 = t1.Duration + op.T2 = t2.Duration - if err := opt.Options.FromBytes(buf.ReadAll()); err != nil { - return nil, err + if err := op.Options.FromBytes(buf.ReadAll()); err != nil { + return err } - return &opt, buf.FinError() + return buf.FinError() } diff --git a/dhcpv6/option_iapd_test.go b/dhcpv6/option_iapd_test.go index 13175f4..2fce999 100644 --- a/dhcpv6/option_iapd_test.go +++ b/dhcpv6/option_iapd_test.go @@ -19,7 +19,8 @@ func TestOptIAPDParseOptIAPD(t *testing.T) { 36, // IAPrefix prefixLength 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // IAPrefix ipv6Prefix } - opt, err := ParseOptIAPD(data) + var opt OptIAPD + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, OptionIAPD, opt.Code()) require.Equal(t, [4]byte{1, 0, 0, 0}, opt.IaId) @@ -33,7 +34,8 @@ func TestOptIAPDParseOptIAPDInvalidLength(t *testing.T) { 0, 0, 0, 1, // T1 // truncated from here } - _, err := ParseOptIAPD(data) + var opt OptIAPD + err := opt.FromBytes(data) require.Error(t, err) } @@ -48,7 +50,8 @@ func TestOptIAPDParseOptIAPDInvalidOptions(t *testing.T) { 36, // IAPrefix prefixLength 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // IAPrefix ipv6Prefix missing last byte } - _, err := ParseOptIAPD(data) + var opt OptIAPD + err := opt.FromBytes(data) require.Error(t, err) } @@ -92,7 +95,8 @@ func TestOptIAPDString(t *testing.T) { 36, // IAPrefix prefixLength 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // IAPrefix ipv6Prefix } - opt, err := ParseOptIAPD(data) + var opt OptIAPD + err := opt.FromBytes(data) require.NoError(t, err) str := opt.String() diff --git a/dhcpv6/option_iaprefix.go b/dhcpv6/option_iaprefix.go index fc41e0a..f7d3e76 100644 --- a/dhcpv6/option_iaprefix.go +++ b/dhcpv6/option_iaprefix.go @@ -74,31 +74,30 @@ func (op *OptIAPrefix) String() string { op.Code(), op.PreferredLifetime, op.ValidLifetime, op.Prefix, op.Options) } -// ParseOptIAPrefix an OptIAPrefix structure from a sequence of bytes. The -// input data does not include option code and length bytes. -func ParseOptIAPrefix(data []byte) (*OptIAPrefix, error) { +// FromBytes an OptIAPrefix structure from a sequence of bytes. The input data +// does not include option code and length bytes. +func (op *OptIAPrefix) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - var opt OptIAPrefix var t1, t2 Duration t1.Unmarshal(buf) t2.Unmarshal(buf) - opt.PreferredLifetime = t1.Duration - opt.ValidLifetime = t2.Duration + op.PreferredLifetime = t1.Duration + op.ValidLifetime = t2.Duration length := buf.Read8() ip := net.IP(buf.CopyN(net.IPv6len)) if length == 0 { - opt.Prefix = nil + op.Prefix = nil } else { - opt.Prefix = &net.IPNet{ + op.Prefix = &net.IPNet{ Mask: net.CIDRMask(int(length), 128), IP: ip, } } - if err := opt.Options.FromBytes(buf.ReadAll()); err != nil { - return nil, err + if err := op.Options.FromBytes(buf.ReadAll()); err != nil { + return err } - return &opt, buf.FinError() + return buf.FinError() } diff --git a/dhcpv6/option_iaprefix_test.go b/dhcpv6/option_iaprefix_test.go index 27d0c95..be7e232 100644 --- a/dhcpv6/option_iaprefix_test.go +++ b/dhcpv6/option_iaprefix_test.go @@ -17,8 +17,8 @@ func TestOptIAPrefix(t *testing.T) { 36, // prefixLength 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // ipv6Prefix } - opt, err := ParseOptIAPrefix(buf) - if err != nil { + var opt OptIAPrefix + if err := opt.FromBytes(buf); err != nil { t.Fatal(err) } want := &OptIAPrefix{ @@ -30,7 +30,7 @@ func TestOptIAPrefix(t *testing.T) { }, Options: PrefixOptions{[]Option{}}, } - if !reflect.DeepEqual(want, opt) { + if !reflect.DeepEqual(want, &opt) { t.Errorf("parseIAPrefix = %v, want %v", opt, want) } } @@ -79,7 +79,8 @@ func TestOptIAPrefixParseInvalidTooShort(t *testing.T) { 36, // prefixLength 0, 0, 0, 0, 0, 0, 0, // truncated ipv6Prefix } - if opt, err := ParseOptIAPrefix(buf); err == nil { + var opt OptIAPrefix + if err := opt.FromBytes(buf); err == nil { t.Fatalf("ParseOptIAPrefix: Expected error on truncated option, got %v", opt) } } @@ -91,7 +92,8 @@ func TestOptIAPrefixString(t *testing.T) { 36, // prefixLength 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ipv6Prefix } - opt, err := ParseOptIAPrefix(buf) + var opt OptIAPrefix + err := opt.FromBytes(buf) require.NoError(t, err) str := opt.String() diff --git a/dhcpv6/option_informationrefreshtime.go b/dhcpv6/option_informationrefreshtime.go index 8b47b46..e0ba43c 100644 --- a/dhcpv6/option_informationrefreshtime.go +++ b/dhcpv6/option_informationrefreshtime.go @@ -35,14 +35,13 @@ func (op *optInformationRefreshTime) String() string { return fmt.Sprintf("%s: %v", op.Code(), op.InformationRefreshtime) } -// parseOptInformationRefreshTime builds an optInformationRefreshTime structure from a sequence -// of bytes. The input data does not include option code and length bytes. -func parseOptInformationRefreshTime(data []byte) (*optInformationRefreshTime, error) { - var opt optInformationRefreshTime +// FromBytes builds an optInformationRefreshTime structure from a sequence of +// bytes. The input data does not include option code and length bytes. +func (op *optInformationRefreshTime) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) var irt Duration irt.Unmarshal(buf) - opt.InformationRefreshtime = irt.Duration - return &opt, buf.FinError() + op.InformationRefreshtime = irt.Duration + return buf.FinError() } diff --git a/dhcpv6/option_informationrefreshtime_test.go b/dhcpv6/option_informationrefreshtime_test.go index 0428a1c..452ac1d 100644 --- a/dhcpv6/option_informationrefreshtime_test.go +++ b/dhcpv6/option_informationrefreshtime_test.go @@ -7,7 +7,8 @@ import ( ) func TestOptInformationRefreshTime(t *testing.T) { - opt, err := parseOptInformationRefreshTime([]byte{0xaa, 0xbb, 0xcc, 0xdd}) + var opt optInformationRefreshTime + err := opt.FromBytes([]byte{0xaa, 0xbb, 0xcc, 0xdd}) if err != nil { t.Fatal(err) } diff --git a/dhcpv6/option_interfaceid.go b/dhcpv6/option_interfaceid.go index 163af7b..a6debba 100644 --- a/dhcpv6/option_interfaceid.go +++ b/dhcpv6/option_interfaceid.go @@ -26,10 +26,9 @@ func (op *optInterfaceID) String() string { return fmt.Sprintf("%s: %v", op.Code(), op.ID) } -// build an optInterfaceID structure from a sequence of bytes. -// The input data does not include option code and length bytes. -func parseOptInterfaceID(data []byte) (*optInterfaceID, error) { - var opt optInterfaceID - opt.ID = append([]byte(nil), data...) - return &opt, nil +// FromBytes builds an optInterfaceID structure from a sequence of bytes. The +// input data does not include option code and length bytes. +func (op *optInterfaceID) FromBytes(data []byte) error { + op.ID = append([]byte(nil), data...) + return nil } diff --git a/dhcpv6/option_interfaceid_test.go b/dhcpv6/option_interfaceid_test.go index 45c1799..b38cadb 100644 --- a/dhcpv6/option_interfaceid_test.go +++ b/dhcpv6/option_interfaceid_test.go @@ -9,8 +9,8 @@ import ( func TestParseOptInterfaceID(t *testing.T) { expected := []byte("DSLAM01 eth2/1/01/21") - opt, err := parseOptInterfaceID(expected) - if err != nil { + var opt optInterfaceID + if err := opt.FromBytes(expected); err != nil { t.Fatal(err) } if url := opt.ID; !bytes.Equal(url, expected) { diff --git a/dhcpv6/option_nontemporaryaddress.go b/dhcpv6/option_nontemporaryaddress.go index 76f6f4c..2734931 100644 --- a/dhcpv6/option_nontemporaryaddress.go +++ b/dhcpv6/option_nontemporaryaddress.go @@ -102,21 +102,20 @@ func (op *OptIANA) LongString(indentSpace int) string { return fmt.Sprintf("%s: IAID=%#x T1=%s T2=%s Options=%s", op.Code(), op.IaId, op.T1, op.T2, op.Options.LongString(indentSpace)) } -// ParseOptIANA builds an OptIANA structure from a sequence of bytes. The +// FromBytes builds an OptIANA structure from a sequence of bytes. The // input data does not include option code and length bytes. -func ParseOptIANA(data []byte) (*OptIANA, error) { - var opt OptIANA +func (op *OptIANA) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - buf.ReadBytes(opt.IaId[:]) + buf.ReadBytes(op.IaId[:]) var t1, t2 Duration t1.Unmarshal(buf) t2.Unmarshal(buf) - opt.T1 = t1.Duration - opt.T2 = t2.Duration + op.T1 = t1.Duration + op.T2 = t2.Duration - if err := opt.Options.FromBytes(buf.ReadAll()); err != nil { - return nil, err + if err := op.Options.FromBytes(buf.ReadAll()); err != nil { + return err } - return &opt, buf.FinError() + return buf.FinError() } diff --git a/dhcpv6/option_nontemporaryaddress_test.go b/dhcpv6/option_nontemporaryaddress_test.go index 1ec58e8..a1105d3 100644 --- a/dhcpv6/option_nontemporaryaddress_test.go +++ b/dhcpv6/option_nontemporaryaddress_test.go @@ -15,7 +15,8 @@ func TestOptIANAParseOptIANA(t *testing.T) { 0, 0, 0, 2, // T2 0, 5, 0, 0x18, 0x24, 1, 0xdb, 0, 0x30, 0x10, 0xc0, 0x8f, 0xfa, 0xce, 0, 0, 0, 0x44, 0, 0, 0, 0, 0xb2, 0x7a, 0, 0, 0xc0, 0x8a, // options } - opt, err := ParseOptIANA(data) + var opt OptIANA + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, OptionIANA, opt.Code()) } @@ -26,7 +27,8 @@ func TestOptIANAParseOptIANAInvalidLength(t *testing.T) { 0, 0, 0, 1, // T1 // truncated from here } - _, err := ParseOptIANA(data) + var opt OptIANA + err := opt.FromBytes(data) require.Error(t, err) } @@ -37,7 +39,8 @@ func TestOptIANAParseOptIANAInvalidOptions(t *testing.T) { 0, 0, 0, 2, // T2 0, 5, 0, 0x18, 0x24, 1, 0xdb, 0, 0x30, 0x10, 0xc0, 0x8f, 0xfa, 0xce, 0, 0, 0, 0x44, 0, 0, 0, 0, 0xb2, 0x7a, // truncated options } - _, err := ParseOptIANA(data) + var opt OptIANA + err := opt.FromBytes(data) require.Error(t, err) } @@ -118,7 +121,8 @@ func TestOptIANAString(t *testing.T) { 0, 0, 0, 2, // T2 0, 5, 0, 0x18, 0x24, 1, 0xdb, 0, 0x30, 0x10, 0xc0, 0x8f, 0xfa, 0xce, 0, 0, 0, 0x44, 0, 0, 0, 0, 0xb2, 0x7a, 0, 0, 0xc0, 0x8a, // options } - opt, err := ParseOptIANA(data) + var opt OptIANA + err := opt.FromBytes(data) require.NoError(t, err) str := opt.String() diff --git a/dhcpv6/option_ntp_server.go b/dhcpv6/option_ntp_server.go index a5b0cfb..69a3e89 100644 --- a/dhcpv6/option_ntp_server.go +++ b/dhcpv6/option_ntp_server.go @@ -90,24 +90,17 @@ const ( // parseNTPSuboption implements the OptionParser interface. func parseNTPSuboption(code OptionCode, data []byte) (Option, error) { var o Option - var err error switch code { case NTPSuboptionSrvAddrCode: - var opt NTPSuboptionSrvAddr - err = opt.FromBytes(data) - o = &opt + o = &NTPSuboptionSrvAddr{} case NTPSuboptionMCAddrCode: - var opt NTPSuboptionMCAddr - err = opt.FromBytes(data) - o = &opt + o = &NTPSuboptionMCAddr{} case NTPSuboptionSrvFQDNCode: - var opt NTPSuboptionSrvFQDN - err = opt.FromBytes(data) - o = &opt + o = &NTPSuboptionSrvFQDN{} default: - o = &OptionGeneric{OptionCode: code, OptionData: append([]byte(nil), data...)} + o = &OptionGeneric{OptionCode: code} } - return o, err + return o, o.FromBytes(data) } // OptNTPServer is an option NTP server as defined by RFC 5908. @@ -120,6 +113,7 @@ func (op *OptNTPServer) Code() OptionCode { return OptionNTPServer } +// FromBytes parses a sequence of bytes into an OptNTPServer object. func (op *OptNTPServer) FromBytes(data []byte) error { return op.Suboptions.FromBytesWithParser(data, parseNTPSuboption) } diff --git a/dhcpv6/option_relaymsg.go b/dhcpv6/option_relaymsg.go index 216f53b..9962756 100644 --- a/dhcpv6/option_relaymsg.go +++ b/dhcpv6/option_relaymsg.go @@ -33,14 +33,10 @@ func (op *optRelayMsg) LongString(indent int) string { return fmt.Sprintf("%s: %v", op.Code(), op.Msg.LongString(indent)) } -// build an optRelayMsg structure from a sequence of bytes. -// The input data does not include option code and length bytes. -func parseOptRelayMsg(data []byte) (*optRelayMsg, error) { +// FromBytes build an optRelayMsg structure from a sequence of bytes. The input +// data does not include option code and length bytes. +func (op *optRelayMsg) FromBytes(data []byte) error { var err error - var opt optRelayMsg - opt.Msg, err = FromBytes(data) - if err != nil { - return nil, err - } - return &opt, nil + op.Msg, err = FromBytes(data) + return err } diff --git a/dhcpv6/option_relaymsg_test.go b/dhcpv6/option_relaymsg_test.go index e77a6c6..0b8e399 100644 --- a/dhcpv6/option_relaymsg_test.go +++ b/dhcpv6/option_relaymsg_test.go @@ -9,7 +9,8 @@ import ( ) func TestRelayMsgParseOptRelayMsg(t *testing.T) { - opt, err := parseOptRelayMsg([]byte{ + var opt optRelayMsg + err := opt.FromBytes([]byte{ 1, // MessageTypeSolicit 0xaa, 0xbb, 0xcc, // transaction ID 0, 8, // option: elapsed time @@ -148,7 +149,8 @@ func TestSample(t *testing.T) { } func TestRelayMsgParseOptRelayMsgTooShort(t *testing.T) { - _, err := parseOptRelayMsg([]byte{ + var opt optRelayMsg + err := opt.FromBytes([]byte{ 1, // MessageTypeSolicit 0xaa, 0xbb, 0xcc, // transaction ID 0, 8, // option: elapsed time @@ -158,7 +160,8 @@ func TestRelayMsgParseOptRelayMsgTooShort(t *testing.T) { } func TestRelayMsgString(t *testing.T) { - opt, err := parseOptRelayMsg([]byte{ + var opt optRelayMsg + err := opt.FromBytes([]byte{ 1, // MessageTypeSolicit 0xaa, 0xbb, 0xcc, // transaction ID 0, 8, // option: elapsed time diff --git a/dhcpv6/option_relayport.go b/dhcpv6/option_relayport.go index 4873693..8bf9eff 100644 --- a/dhcpv6/option_relayport.go +++ b/dhcpv6/option_relayport.go @@ -32,11 +32,10 @@ func (op *optRelayPort) String() string { return fmt.Sprintf("%s: %d", op.Code(), op.DownstreamSourcePort) } -// build an optRelayPort structure from a sequence of bytes. -// The input data does not include option code and length bytes. -func parseOptRelayPort(data []byte) (*optRelayPort, error) { - var opt optRelayPort +// FromBytes build an optRelayPort structure from a sequence of bytes. The +// input data does not include option code and length bytes. +func (op *optRelayPort) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - opt.DownstreamSourcePort = buf.Read16() - return &opt, buf.FinError() + op.DownstreamSourcePort = buf.Read16() + return buf.FinError() } diff --git a/dhcpv6/option_relayport_test.go b/dhcpv6/option_relayport_test.go index 124af62..d80e268 100644 --- a/dhcpv6/option_relayport_test.go +++ b/dhcpv6/option_relayport_test.go @@ -7,9 +7,10 @@ import ( ) func TestParseRelayPort(t *testing.T) { - opt, err := parseOptRelayPort([]byte{0x12, 0x32}) + var opt optRelayPort + err := opt.FromBytes([]byte{0x12, 0x32}) require.NoError(t, err) - require.Equal(t, &optRelayPort{DownstreamSourcePort: 0x1232}, opt) + require.Equal(t, optRelayPort{DownstreamSourcePort: 0x1232}, opt) } func TestRelayPortToBytes(t *testing.T) { diff --git a/dhcpv6/option_remoteid.go b/dhcpv6/option_remoteid.go index 9833149..d07b0a2 100644 --- a/dhcpv6/option_remoteid.go +++ b/dhcpv6/option_remoteid.go @@ -31,12 +31,11 @@ func (op *OptRemoteID) String() string { ) } -// ParseOptRemoteId builds an OptRemoteId structure from a sequence of bytes. -// The input data does not include option code and length bytes. -func ParseOptRemoteID(data []byte) (*OptRemoteID, error) { - var opt OptRemoteID +// FromBytes builds an OptRemoteId structure from a sequence of bytes. The +// input data does not include option code and length bytes. +func (op *OptRemoteID) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - opt.EnterpriseNumber = buf.Read32() - opt.RemoteID = buf.ReadAll() - return &opt, buf.FinError() + op.EnterpriseNumber = buf.Read32() + op.RemoteID = buf.ReadAll() + return buf.FinError() } diff --git a/dhcpv6/option_remoteid_test.go b/dhcpv6/option_remoteid_test.go index 77835de..d8f848b 100644 --- a/dhcpv6/option_remoteid_test.go +++ b/dhcpv6/option_remoteid_test.go @@ -11,8 +11,8 @@ func TestOptRemoteID(t *testing.T) { expected := []byte{0xaa, 0xbb, 0xcc, 0xdd} remoteId := []byte("DSLAM01 eth2/1/01/21") expected = append(expected, remoteId...) - opt, err := ParseOptRemoteID(expected) - if err != nil { + var opt OptRemoteID + if err := opt.FromBytes(expected); err != nil { t.Fatal(err) } if en := opt.EnterpriseNumber; en != 0xaabbccdd { @@ -37,7 +37,8 @@ func TestOptRemoteIDToBytes(t *testing.T) { func TestOptRemoteIDParseOptRemoteIDTooShort(t *testing.T) { buf := []byte{0xaa, 0xbb, 0xcc} - _, err := ParseOptRemoteID(buf) + var opt OptRemoteID + err := opt.FromBytes(buf) require.Error(t, err, "A short option should return an error") } @@ -46,7 +47,8 @@ func TestOptRemoteIDString(t *testing.T) { remoteId := []byte("Test1234") buf = append(buf, remoteId...) - opt, err := ParseOptRemoteID(buf) + var opt OptRemoteID + err := opt.FromBytes(buf) require.NoError(t, err) str := opt.String() require.Contains( diff --git a/dhcpv6/option_serverid.go b/dhcpv6/option_serverid.go index bdfc290..4c35cc1 100644 --- a/dhcpv6/option_serverid.go +++ b/dhcpv6/option_serverid.go @@ -22,12 +22,10 @@ func (op *optServerID) String() string { return fmt.Sprintf("%s: %v", op.Code(), op.DUID) } -// parseOptServerID builds an optServerID structure from a sequence of bytes. -// The input data does not include option code and length bytes. -func parseOptServerID(data []byte) (*optServerID, error) { - sid, err := DUIDFromBytes(data) - if err != nil { - return nil, err - } - return &optServerID{sid}, nil +// FromBytes builds an optServerID structure from a sequence of bytes. The +// input data does not include option code and length bytes. +func (op *optServerID) FromBytes(data []byte) error { + var err error + op.DUID, err = DUIDFromBytes(data) + return err } diff --git a/dhcpv6/option_serverid_test.go b/dhcpv6/option_serverid_test.go index 556f515..3422287 100644 --- a/dhcpv6/option_serverid_test.go +++ b/dhcpv6/option_serverid_test.go @@ -14,7 +14,8 @@ func TestParseOptServerID(t *testing.T) { 0, 1, // hwtype ethernet 0, 1, 2, 3, 4, 5, // hw addr } - opt, err := parseOptServerID(data) + var opt optServerID + err := opt.FromBytes(data) require.NoError(t, err) want := OptServerID( &DUIDLL{ @@ -22,7 +23,7 @@ func TestParseOptServerID(t *testing.T) { LinkLayerAddr: net.HardwareAddr{0, 1, 2, 3, 4, 5}, }, ) - require.Equal(t, opt, want) + require.Equal(t, &opt, want) } func TestOptServerIdToBytes(t *testing.T) { @@ -46,7 +47,8 @@ func TestOptServerIdDecodeEncode(t *testing.T) { 0, 1, // hwtype ethernet 5, 4, 3, 2, 1, 0, // hw addr } - opt, err := parseOptServerID(data) + var opt optServerID + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, data, opt.ToBytes()) } @@ -73,7 +75,8 @@ func TestOptServerIdparseOptServerIDBogusDUID(t *testing.T) { 1, 2, 3, 4, 5, 6, 7, 8, 9, // a UUID should be 18 bytes not 17 10, 11, 12, 13, 14, 15, 16, 17, } - _, err := parseOptServerID(data) + var opt optServerID + err := opt.FromBytes(data) require.Error(t, err, "A truncated OptServerId DUID should return an error") } @@ -81,6 +84,7 @@ func TestOptServerIdparseOptServerIDInvalidTooShort(t *testing.T) { data := []byte{ 0, // truncated: DUIDs are at least 2 bytes } - _, err := parseOptServerID(data) + var opt optServerID + err := opt.FromBytes(data) require.Error(t, err, "A truncated OptServerId should return an error") } diff --git a/dhcpv6/option_statuscode.go b/dhcpv6/option_statuscode.go index 067b973..c745bc1 100644 --- a/dhcpv6/option_statuscode.go +++ b/dhcpv6/option_statuscode.go @@ -35,12 +35,11 @@ func (op *OptStatusCode) String() string { op.Code(), op.StatusCode, op.StatusCode, op.StatusMessage) } -// ParseOptStatusCode builds an OptStatusCode structure from a sequence of -// bytes. The input data does not include option code and length bytes. -func ParseOptStatusCode(data []byte) (*OptStatusCode, error) { - var opt OptStatusCode +// FromBytes builds an OptStatusCode structure from a sequence of bytes. The +// input data does not include option code and length bytes. +func (op *OptStatusCode) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - opt.StatusCode = iana.StatusCode(buf.Read16()) - opt.StatusMessage = string(buf.ReadAll()) - return &opt, buf.FinError() + op.StatusCode = iana.StatusCode(buf.Read16()) + op.StatusMessage = string(buf.ReadAll()) + return buf.FinError() } diff --git a/dhcpv6/option_statuscode_test.go b/dhcpv6/option_statuscode_test.go index 82225e0..4582909 100644 --- a/dhcpv6/option_statuscode_test.go +++ b/dhcpv6/option_statuscode_test.go @@ -12,7 +12,8 @@ func TestParseOptStatusCode(t *testing.T) { 0, 5, // StatusUseMulticast 'u', 's', 'e', ' ', 'm', 'u', 'l', 't', 'i', 'c', 'a', 's', 't', } - opt, err := ParseOptStatusCode(data) + var opt OptStatusCode + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, iana.StatusUseMulticast, opt.StatusCode) require.Equal(t, "use multicast", opt.StatusMessage) @@ -32,7 +33,8 @@ func TestOptStatusCodeToBytes(t *testing.T) { } func TestOptStatusCodeParseOptStatusCodeTooShort(t *testing.T) { - _, err := ParseOptStatusCode([]byte{0}) + var opt OptStatusCode + err := opt.FromBytes([]byte{0}) require.Error(t, err, "ParseOptStatusCode: Expected error on truncated option") } @@ -41,7 +43,8 @@ func TestOptStatusCodeString(t *testing.T) { 0, 5, // StatusUseMulticast 'u', 's', 'e', ' ', 'm', 'u', 'l', 't', 'i', 'c', 'a', 's', 't', } - opt, err := ParseOptStatusCode(data) + var opt OptStatusCode + err := opt.FromBytes(data) require.NoError(t, err) require.Contains( diff --git a/dhcpv6/option_temporaryaddress.go b/dhcpv6/option_temporaryaddress.go index 4a79bac..8ccbe7b 100644 --- a/dhcpv6/option_temporaryaddress.go +++ b/dhcpv6/option_temporaryaddress.go @@ -38,15 +38,14 @@ func (op *OptIATA) LongString(indentSpace int) string { return fmt.Sprintf("%s: IAID=%#x Options=%v", op.Code(), op.IaId, op.Options.LongString(indentSpace)) } -// ParseOptIATA builds an OptIATA structure from a sequence of bytes. The -// input data does not include option code and length bytes. -func ParseOptIATA(data []byte) (*OptIATA, error) { - var opt OptIATA +// FromBytes builds an OptIATA structure from a sequence of bytes. The input +// data does not include option code and length bytes. +func (op *OptIATA) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - buf.ReadBytes(opt.IaId[:]) + buf.ReadBytes(op.IaId[:]) - if err := opt.Options.FromBytes(buf.ReadAll()); err != nil { - return nil, err + if err := op.Options.FromBytes(buf.ReadAll()); err != nil { + return err } - return &opt, buf.FinError() + return buf.FinError() } diff --git a/dhcpv6/option_temporaryaddress_test.go b/dhcpv6/option_temporaryaddress_test.go index 9b48d5a..8704d5c 100644 --- a/dhcpv6/option_temporaryaddress_test.go +++ b/dhcpv6/option_temporaryaddress_test.go @@ -13,7 +13,8 @@ func TestOptIATAParseOptIATA(t *testing.T) { 1, 0, 0, 0, // IAID 0, 5, 0, 0x18, 0x24, 1, 0xdb, 0, 0x30, 0x10, 0xc0, 0x8f, 0xfa, 0xce, 0, 0, 0, 0x44, 0, 0, 0, 0, 0xb2, 0x7a, 0, 0, 0xc0, 0x8a, // options } - opt, err := ParseOptIATA(data) + var opt OptIATA + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, OptionIATA, opt.Code()) } @@ -22,7 +23,8 @@ func TestOptIATAParseOptIATAInvalidLength(t *testing.T) { data := []byte{ 1, 0, 0, // truncated IAID } - _, err := ParseOptIATA(data) + var opt OptIATA + err := opt.FromBytes(data) require.Error(t, err) } @@ -31,7 +33,8 @@ func TestOptIATAParseOptIATAInvalidOptions(t *testing.T) { 1, 0, 0, 0, // IAID 0, 5, 0, 0x18, 0x24, 1, 0xdb, 0, 0x30, 0x10, 0xc0, 0x8f, 0xfa, 0xce, 0, 0, 0, 0x44, 0, 0, 0, 0, 0xb2, 0x7a, // truncated options } - _, err := ParseOptIATA(data) + var opt OptIATA + err := opt.FromBytes(data) require.Error(t, err) } @@ -106,7 +109,8 @@ func TestOptIATAString(t *testing.T) { 1, 0, 0, 0, // IAID 0, 5, 0, 0x18, 0x24, 1, 0xdb, 0, 0x30, 0x10, 0xc0, 0x8f, 0xfa, 0xce, 0, 0, 0, 0x44, 0, 0, 0, 0, 0xb2, 0x7a, 0, 0, 0xc0, 0x8a, // options } - opt, err := ParseOptIATA(data) + var opt OptIATA + err := opt.FromBytes(data) require.NoError(t, err) str := opt.String() diff --git a/dhcpv6/option_userclass.go b/dhcpv6/option_userclass.go index 00abcbd..643fdd1 100644 --- a/dhcpv6/option_userclass.go +++ b/dhcpv6/option_userclass.go @@ -38,17 +38,16 @@ func (op *OptUserClass) String() string { return fmt.Sprintf("%s: [%s]", op.Code(), strings.Join(ucStrings, ", ")) } -// ParseOptUserClass builds an OptUserClass structure from a sequence of -// bytes. The input data does not include option code and length bytes. -func ParseOptUserClass(data []byte) (*OptUserClass, error) { - var opt OptUserClass +// FromBytes builds an OptUserClass structure from a sequence of bytes. The +// input data does not include option code and length bytes. +func (op *OptUserClass) FromBytes(data []byte) error { if len(data) == 0 { - return nil, fmt.Errorf("user class option must not be empty") + return fmt.Errorf("user class option must not be empty") } buf := uio.NewBigEndianBuffer(data) for buf.Has(2) { len := buf.Read16() - opt.UserClasses = append(opt.UserClasses, buf.CopyN(int(len))) + op.UserClasses = append(op.UserClasses, buf.CopyN(int(len))) } - return &opt, buf.FinError() + return buf.FinError() } diff --git a/dhcpv6/option_userclass_test.go b/dhcpv6/option_userclass_test.go index 50bc438..2612da1 100644 --- a/dhcpv6/option_userclass_test.go +++ b/dhcpv6/option_userclass_test.go @@ -10,7 +10,8 @@ func TestParseOptUserClass(t *testing.T) { expected := []byte{ 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't', } - opt, err := ParseOptUserClass(expected) + var opt OptUserClass + err := opt.FromBytes(expected) require.NoError(t, err) require.Equal(t, 1, len(opt.UserClasses)) require.Equal(t, []byte("linuxboot"), opt.UserClasses[0]) @@ -21,7 +22,8 @@ func TestParseOptUserClassMultiple(t *testing.T) { 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't', 0, 4, 't', 'e', 's', 't', } - opt, err := ParseOptUserClass(expected) + var opt OptUserClass + err := opt.FromBytes(expected) require.NoError(t, err) require.Equal(t, len(opt.UserClasses), 2) require.Equal(t, []byte("linuxboot"), opt.UserClasses[0]) @@ -30,7 +32,8 @@ func TestParseOptUserClassMultiple(t *testing.T) { func TestParseOptUserClassNone(t *testing.T) { expected := []byte{} - _, err := ParseOptUserClass(expected) + var opt OptUserClass + err := opt.FromBytes(expected) require.Error(t, err) } @@ -65,14 +68,15 @@ func TestOptUserClassParseOptUserClassTooShort(t *testing.T) { 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't', 0, 4, 't', 'e', } - _, err := ParseOptUserClass(buf) + var opt OptUserClass + err := opt.FromBytes(buf) require.Error(t, err, "ParseOptUserClass() should error if given truncated user classes") buf = []byte{ 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't', 0, } - _, err = ParseOptUserClass(buf) + err = opt.FromBytes(buf) require.Error(t, err, "ParseOptUserClass() should error if given a truncated length") } @@ -81,7 +85,8 @@ func TestOptUserClassString(t *testing.T) { 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't', 0, 4, 't', 'e', 's', 't', } - opt, err := ParseOptUserClass(data) + var opt OptUserClass + err := opt.FromBytes(data) require.NoError(t, err) require.Contains( diff --git a/dhcpv6/option_vendor_opts.go b/dhcpv6/option_vendor_opts.go index 11811c0..8412fd9 100644 --- a/dhcpv6/option_vendor_opts.go +++ b/dhcpv6/option_vendor_opts.go @@ -38,16 +38,15 @@ func (op *OptVendorOpts) LongString(indent int) string { return fmt.Sprintf("%s: EnterpriseNumber=%v VendorOptions=%s", op.Code(), op.EnterpriseNumber, op.VendorOpts.LongString(indent)) } -// 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) { - var opt OptVendorOpts +// FromBytes builds an OptVendorOpts structure from a sequence of bytes. The +// input data does not include option code and length bytes. +func (op *OptVendorOpts) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - opt.EnterpriseNumber = buf.Read32() - if err := opt.VendorOpts.FromBytesWithParser(buf.ReadAll(), vendParseOption); err != nil { - return nil, err + op.EnterpriseNumber = buf.Read32() + if err := op.VendorOpts.FromBytesWithParser(buf.ReadAll(), vendParseOption); err != nil { + return err } - return &opt, buf.FinError() + return buf.FinError() } // vendParseOption builds a GenericOption from a slice of bytes diff --git a/dhcpv6/option_vendor_opts_test.go b/dhcpv6/option_vendor_opts_test.go index f6c2b2a..5caba9c 100644 --- a/dhcpv6/option_vendor_opts_test.go +++ b/dhcpv6/option_vendor_opts_test.go @@ -17,13 +17,16 @@ func TestOptVendorOpts(t *testing.T) { expectedOpts := OptVendorOpts{} var vendorOpts []Option expectedOpts.VendorOpts = append(vendorOpts, &OptionGeneric{OptionCode: 1, OptionData: optData}) - opt, err := ParseOptVendorOpts(expected) + + var opt OptVendorOpts + err := opt.FromBytes(expected) require.NoError(t, err) require.Equal(t, uint32(0xaabbccdd), opt.EnterpriseNumber) require.Equal(t, expectedOpts.VendorOpts, opt.VendorOpts) shortData := make([]byte, 1) - _, err = ParseOptVendorOpts(shortData) + var opt2 OptVendorOpts + err = opt2.FromBytes(shortData) require.Error(t, err) } diff --git a/dhcpv6/option_vendorclass.go b/dhcpv6/option_vendorclass.go index 33297dc..954dbd0 100644 --- a/dhcpv6/option_vendorclass.go +++ b/dhcpv6/option_vendorclass.go @@ -39,18 +39,18 @@ func (op *OptVendorClass) String() string { return fmt.Sprintf("%s: {EnterpriseNumber=%d Data=[%s]}", op.Code(), 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) { - var opt OptVendorClass +// FromBytes builds an OptVendorClass structure from a sequence of bytes. The +// input data does not include option code and length bytes. +func (op *OptVendorClass) FromBytes(data []byte) error { buf := uio.NewBigEndianBuffer(data) - opt.EnterpriseNumber = buf.Read32() + *op = OptVendorClass{} + op.EnterpriseNumber = buf.Read32() for buf.Has(2) { len := buf.Read16() - opt.Data = append(opt.Data, buf.CopyN(int(len))) + op.Data = append(op.Data, buf.CopyN(int(len))) } - if len(opt.Data) < 1 { - return nil, errors.New("ParseOptVendorClass: at least one vendor class data is required") + if len(op.Data) < 1 { + return errors.New("ParseOptVendorClass: at least one vendor class data is required") } - return &opt, buf.FinError() + return buf.FinError() } diff --git a/dhcpv6/option_vendorclass_test.go b/dhcpv6/option_vendorclass_test.go index 819f5f6..c691176 100644 --- a/dhcpv6/option_vendorclass_test.go +++ b/dhcpv6/option_vendorclass_test.go @@ -12,7 +12,8 @@ func TestParseOptVendorClass(t *testing.T) { 0, 10, 'H', 'T', 'T', 'P', 'C', 'l', 'i', 'e', 'n', 't', 0, 4, 't', 'e', 's', 't', } - opt, err := ParseOptVendorClass(data) + var opt OptVendorClass + err := opt.FromBytes(data) require.NoError(t, err) require.Equal(t, OptionVendorClass, opt.Code()) require.Equal(t, 2, len(opt.Data)) @@ -42,13 +43,14 @@ func TestOptVendorClassParseOptVendorClassMalformed(t *testing.T) { buf := []byte{ 0xaa, 0xbb, // truncated EnterpriseNumber } - _, err := ParseOptVendorClass(buf) + var opt OptVendorClass + err := opt.FromBytes(buf) require.Error(t, err, "ParseOptVendorClass() should error if given truncated EnterpriseNumber") buf = []byte{ 0xaa, 0xbb, 0xcc, 0xdd, // EnterpriseNumber } - _, err = ParseOptVendorClass(buf) + err = opt.FromBytes(buf) require.Error(t, err, "ParseOptVendorClass() should error if given no vendor classes") buf = []byte{ @@ -56,7 +58,7 @@ func TestOptVendorClassParseOptVendorClassMalformed(t *testing.T) { 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't', 0, 4, 't', 'e', } - _, err = ParseOptVendorClass(buf) + err = opt.FromBytes(buf) require.Error(t, err, "ParseOptVendorClass() should error if given truncated vendor classes") buf = []byte{ @@ -64,7 +66,7 @@ func TestOptVendorClassParseOptVendorClassMalformed(t *testing.T) { 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't', 0, } - _, err = ParseOptVendorClass(buf) + err = opt.FromBytes(buf) require.Error(t, err, "ParseOptVendorClass() should error if given a truncated length") } @@ -74,7 +76,8 @@ func TestOptVendorClassString(t *testing.T) { 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't', 0, 4, 't', 'e', 's', 't', } - opt, err := ParseOptVendorClass(data) + var opt OptVendorClass + err := opt.FromBytes(data) require.NoError(t, err) str := opt.String() diff --git a/dhcpv6/options.go b/dhcpv6/options.go index 467c643..9d7da4d 100644 --- a/dhcpv6/options.go +++ b/dhcpv6/options.go @@ -12,6 +12,7 @@ type Option interface { Code() OptionCode ToBytes() []byte String() string + FromBytes([]byte) error } type OptionGeneric struct { @@ -34,6 +35,12 @@ func (og *OptionGeneric) String() string { return fmt.Sprintf("%s: %v", og.OptionCode, og.OptionData) } +// FromBytes resets OptionData to p. +func (og *OptionGeneric) FromBytes(p []byte) error { + og.OptionData = append([]byte(nil), p...) + return nil +} + // ParseOption parses data according to the given code. func ParseOption(code OptionCode, optData []byte) (Option, error) { // Parse a sequence of bytes as a single DHCPv6 option. @@ -44,75 +51,133 @@ func ParseOption(code OptionCode, optData []byte) (Option, error) { ) switch code { case OptionClientID: - opt, err = parseOptClientID(optData) + var o optClientID + err = o.FromBytes(optData) + opt = &o case OptionServerID: - opt, err = parseOptServerID(optData) + var o optServerID + err = o.FromBytes(optData) + opt = &o case OptionIANA: - opt, err = ParseOptIANA(optData) + var o OptIANA + err = o.FromBytes(optData) + opt = &o case OptionIATA: - opt, err = ParseOptIATA(optData) + var o OptIATA + err = o.FromBytes(optData) + opt = &o case OptionIAAddr: - opt, err = ParseOptIAAddress(optData) + var o OptIAAddress + err = o.FromBytes(optData) + opt = &o case OptionORO: var o optRequestedOption err = o.FromBytes(optData) opt = &o case OptionElapsedTime: - opt, err = parseOptElapsedTime(optData) + var o optElapsedTime + err = o.FromBytes(optData) + opt = &o case OptionRelayMsg: - opt, err = parseOptRelayMsg(optData) + var o optRelayMsg + err = o.FromBytes(optData) + opt = &o case OptionStatusCode: - opt, err = ParseOptStatusCode(optData) + var o OptStatusCode + err = o.FromBytes(optData) + opt = &o case OptionUserClass: - opt, err = ParseOptUserClass(optData) + var o OptUserClass + err = o.FromBytes(optData) + opt = &o case OptionVendorClass: - opt, err = ParseOptVendorClass(optData) + var o OptVendorClass + err = o.FromBytes(optData) + opt = &o case OptionVendorOpts: - opt, err = ParseOptVendorOpts(optData) + var o OptVendorOpts + err = o.FromBytes(optData) + opt = &o case OptionInterfaceID: - opt, err = parseOptInterfaceID(optData) + var o optInterfaceID + err = o.FromBytes(optData) + opt = &o case OptionDNSRecursiveNameServer: - opt, err = parseOptDNS(optData) + var o optDNS + err = o.FromBytes(optData) + opt = &o case OptionDomainSearchList: - opt, err = parseOptDomainSearchList(optData) + var o optDomainSearchList + err = o.FromBytes(optData) + opt = &o case OptionIAPD: - opt, err = ParseOptIAPD(optData) + var o OptIAPD + err = o.FromBytes(optData) + opt = &o case OptionIAPrefix: - opt, err = ParseOptIAPrefix(optData) + var o OptIAPrefix + err = o.FromBytes(optData) + opt = &o case OptionInformationRefreshTime: - opt, err = parseOptInformationRefreshTime(optData) + var o optInformationRefreshTime + err = o.FromBytes(optData) + opt = &o case OptionRemoteID: - opt, err = ParseOptRemoteID(optData) + var o OptRemoteID + err = o.FromBytes(optData) + opt = &o case OptionFQDN: - opt, err = ParseOptFQDN(optData) + var o OptFQDN + err = o.FromBytes(optData) + opt = &o case OptionNTPServer: var o OptNTPServer err = o.FromBytes(optData) opt = &o case OptionBootfileURL: - opt, err = parseOptBootFileURL(optData) + var o optBootFileURL + err = o.FromBytes(optData) + opt = &o case OptionBootfileParam: - opt, err = parseOptBootFileParam(optData) + var o optBootFileParam + err = o.FromBytes(optData) + opt = &o case OptionClientArchType: - opt, err = parseOptClientArchType(optData) + var o optClientArchType + err = o.FromBytes(optData) + opt = &o case OptionNII: var o OptNetworkInterfaceID err = o.FromBytes(optData) opt = &o case OptionClientLinkLayerAddr: - opt, err = parseOptClientLinkLayerAddress(optData) + var o optClientLinkLayerAddress + err = o.FromBytes(optData) + opt = &o case OptionDHCPv4Msg: - opt, err = ParseOptDHCPv4Msg(optData) + var o OptDHCPv4Msg + err = o.FromBytes(optData) + opt = &o case OptionDHCP4oDHCP6Server: - opt, err = ParseOptDHCP4oDHCP6Server(optData) + var o OptDHCP4oDHCP6Server + err = o.FromBytes(optData) + opt = &o case Option4RD: - opt, err = ParseOpt4RD(optData) + var o Opt4RD + err = o.FromBytes(optData) + opt = &o case Option4RDMapRule: - opt, err = ParseOpt4RDMapRule(optData) + var o Opt4RDMapRule + err = o.FromBytes(optData) + opt = &o case Option4RDNonMapRule: - opt, err = ParseOpt4RDNonMapRule(optData) + var o Opt4RDNonMapRule + err = o.FromBytes(optData) + opt = &o case OptionRelayPort: - opt, err = parseOptRelayPort(optData) + var o optRelayPort + err = o.FromBytes(optData) + opt = &o default: opt = &OptionGeneric{OptionCode: code, OptionData: optData} } |