summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChris Koch <chrisko@google.com>2023-02-18 20:31:32 -0800
committerChris K <c@chrisko.ch>2023-02-19 22:39:16 -0800
commit336d4b9bd652b2bf0bc1bd0feae3f2f51009c13f (patch)
tree9c99ebb8f3067a39981d8bea07109fd7e7ba0d17
parent1e0fe5ce427973ca92a0dfb1a06a252ddb0dd4be (diff)
dhcpv6: convert every Parse function to FromBytes
Signed-off-by: Chris Koch <chrisko@google.com>
-rw-r--r--dhcpv6/dhcpv6message.go8
-rw-r--r--dhcpv6/option_archtype.go8
-rw-r--r--dhcpv6/option_archtype_test.go9
-rw-r--r--dhcpv6/option_bootfileparam.go22
-rw-r--r--dhcpv6/option_bootfileparam_test.go8
-rw-r--r--dhcpv6/option_bootfileurl.go17
-rw-r--r--dhcpv6/option_bootfileurl_test.go6
-rw-r--r--dhcpv6/option_clientid.go12
-rw-r--r--dhcpv6/option_clientid_test.go14
-rw-r--r--dhcpv6/option_clientlinklayeraddress.go13
-rw-r--r--dhcpv6/option_clientlinklayeraddress_test.go3
-rw-r--r--dhcpv6/option_dhcpv4_msg.go12
-rw-r--r--dhcpv6/option_dhcpv4_msg_test.go3
-rw-r--r--dhcpv6/option_dhcpv4_o_dhcpv6_server.go12
-rw-r--r--dhcpv6/option_dhcpv4_o_dhcpv6_server_test.go9
-rw-r--r--dhcpv6/option_dns.go12
-rw-r--r--dhcpv6/option_dns_test.go6
-rw-r--r--dhcpv6/option_domainsearchlist.go14
-rw-r--r--dhcpv6/option_domainsearchlist_test.go6
-rw-r--r--dhcpv6/option_elapsedtime.go9
-rw-r--r--dhcpv6/option_elapsedtime_test.go8
-rw-r--r--dhcpv6/option_fqdn.go13
-rw-r--r--dhcpv6/option_fqdn_test.go3
-rw-r--r--dhcpv6/option_iaaddress.go20
-rw-r--r--dhcpv6/option_iaaddress_test.go12
-rw-r--r--dhcpv6/option_iapd.go19
-rw-r--r--dhcpv6/option_iapd_test.go12
-rw-r--r--dhcpv6/option_iaprefix.go21
-rw-r--r--dhcpv6/option_iaprefix_test.go12
-rw-r--r--dhcpv6/option_informationrefreshtime.go11
-rw-r--r--dhcpv6/option_informationrefreshtime_test.go3
-rw-r--r--dhcpv6/option_interfaceid.go11
-rw-r--r--dhcpv6/option_interfaceid_test.go4
-rw-r--r--dhcpv6/option_nontemporaryaddress.go17
-rw-r--r--dhcpv6/option_nontemporaryaddress_test.go12
-rw-r--r--dhcpv6/option_ntp_server.go18
-rw-r--r--dhcpv6/option_relaymsg.go14
-rw-r--r--dhcpv6/option_relaymsg_test.go9
-rw-r--r--dhcpv6/option_relayport.go11
-rw-r--r--dhcpv6/option_relayport_test.go5
-rw-r--r--dhcpv6/option_remoteid.go13
-rw-r--r--dhcpv6/option_remoteid_test.go10
-rw-r--r--dhcpv6/option_serverid.go14
-rw-r--r--dhcpv6/option_serverid_test.go14
-rw-r--r--dhcpv6/option_statuscode.go13
-rw-r--r--dhcpv6/option_statuscode_test.go9
-rw-r--r--dhcpv6/option_temporaryaddress.go15
-rw-r--r--dhcpv6/option_temporaryaddress_test.go12
-rw-r--r--dhcpv6/option_userclass.go13
-rw-r--r--dhcpv6/option_userclass_test.go17
-rw-r--r--dhcpv6/option_vendor_opts.go15
-rw-r--r--dhcpv6/option_vendor_opts_test.go7
-rw-r--r--dhcpv6/option_vendorclass.go18
-rw-r--r--dhcpv6/option_vendorclass_test.go15
-rw-r--r--dhcpv6/options.go123
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}
}