summaryrefslogtreecommitdiffhomepage
path: root/dhcpv6
diff options
context:
space:
mode:
authorDavid Barr <38654497+davebarrau@users.noreply.github.com>2018-10-12 11:09:04 +1100
committerinsomniac <insomniacslk@users.noreply.github.com>2018-10-11 17:09:04 -0700
commitdc01165c86340093eacf62c0856ae4e2164a4845 (patch)
tree9ca76ae4103c3e63cd86620fdec230e5cfe5b78d /dhcpv6
parentee671d361777cc640550bab38cc6b0d412396f80 (diff)
Add some more DHCPv6 option tests. (#171)
* Add some more DHCPv6 option tests. * Remove AddRequestedOption() duplicate detection test due to failing on Go 1.9
Diffstat (limited to 'dhcpv6')
-rw-r--r--dhcpv6/option_archtype_test.go9
-rw-r--r--dhcpv6/option_bootfileurl_test.go3
-rw-r--r--dhcpv6/option_clientid_test.go34
-rw-r--r--dhcpv6/option_dnsrecursivenameserver_test.go16
-rw-r--r--dhcpv6/option_domainsearchlist_test.go19
-rw-r--r--dhcpv6/option_elapsedtime_test.go10
-rw-r--r--dhcpv6/option_iaaddress_test.go28
-rw-r--r--dhcpv6/option_iaprefix_test.go44
-rw-r--r--dhcpv6/option_interfaceid_test.go19
-rw-r--r--dhcpv6/option_nii_test.go70
-rw-r--r--dhcpv6/option_nontemporaryaddress_test.go29
-rw-r--r--dhcpv6/option_prefixdelegation_test.go58
-rw-r--r--dhcpv6/option_relaymsg_test.go29
-rw-r--r--dhcpv6/option_remoteid_test.go41
-rw-r--r--dhcpv6/option_requestedoption_test.go38
-rw-r--r--dhcpv6/option_serverid_test.go34
-rw-r--r--dhcpv6/option_statuscode_test.go25
-rw-r--r--dhcpv6/option_userclass_test.go32
-rw-r--r--dhcpv6/option_vendorclass_test.go59
19 files changed, 564 insertions, 33 deletions
diff --git a/dhcpv6/option_archtype_test.go b/dhcpv6/option_archtype_test.go
index 1848e55..d5b2b99 100644
--- a/dhcpv6/option_archtype_test.go
+++ b/dhcpv6/option_archtype_test.go
@@ -13,7 +13,7 @@ func TestParseOptClientArchType(t *testing.T) {
}
opt, err := ParseOptClientArchType(data)
require.NoError(t, err)
- require.Equal(t, opt.ArchTypes[0], iana.EFI_IA32)
+ require.Equal(t, iana.EFI_IA32, opt.ArchTypes[0])
}
func TestParseOptClientArchTypeInvalid(t *testing.T) {
@@ -33,13 +33,14 @@ func TestOptClientArchTypeParseAndToBytes(t *testing.T) {
}
opt, err := ParseOptClientArchType(data)
require.NoError(t, err)
- require.Equal(t, opt.ToBytes(), expected)
+ require.Equal(t, expected, opt.ToBytes())
}
func TestOptClientArchType(t *testing.T) {
opt := OptClientArchType{
ArchTypes: []iana.ArchType{iana.EFI_ITANIUM},
}
- require.Equal(t, opt.Length(), 2)
- require.Equal(t, opt.Code(), OptionClientArchType)
+ require.Equal(t, 2, opt.Length())
+ require.Equal(t, OptionClientArchType, opt.Code())
+ require.Contains(t, opt.String(), "archtype=EFI Itanium", "String() should contain the correct ArchType output")
}
diff --git a/dhcpv6/option_bootfileurl_test.go b/dhcpv6/option_bootfileurl_test.go
index 6f7e077..f93dc47 100644
--- a/dhcpv6/option_bootfileurl_test.go
+++ b/dhcpv6/option_bootfileurl_test.go
@@ -3,6 +3,8 @@ package dhcpv6
import (
"bytes"
"testing"
+
+ "github.com/stretchr/testify/require"
)
func TestOptBootFileURL(t *testing.T) {
@@ -17,6 +19,7 @@ func TestOptBootFileURL(t *testing.T) {
if url := opt.BootFileURL; !bytes.Equal(url, expected) {
t.Fatalf("Invalid boot file URL. Expected %v, got %v", expected, url)
}
+ require.Contains(t, opt.String(), "BootFileUrl=https://insomniac.slackware.it", "String() should contain the correct BootFileUrl output")
}
func TestOptBootFileURLToBytes(t *testing.T) {
diff --git a/dhcpv6/option_clientid_test.go b/dhcpv6/option_clientid_test.go
index 77839f3..872651e 100644
--- a/dhcpv6/option_clientid_test.go
+++ b/dhcpv6/option_clientid_test.go
@@ -16,9 +16,9 @@ func TestParseOptClientId(t *testing.T) {
}
opt, err := ParseOptClientId(data)
require.NoError(t, err)
- require.Equal(t, opt.Cid.Type, DUID_LL)
- require.Equal(t, opt.Cid.HwType, iana.HwTypeEthernet)
- require.Equal(t, opt.Cid.LinkLayerAddr, net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5}))
+ require.Equal(t, DUID_LL, opt.Cid.Type)
+ require.Equal(t, iana.HwTypeEthernet, opt.Cid.HwType)
+ require.Equal(t, net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5}), opt.Cid.LinkLayerAddr)
}
func TestOptClientIdToBytes(t *testing.T) {
@@ -62,6 +62,30 @@ func TestOptionClientId(t *testing.T) {
LinkLayerAddr: net.HardwareAddr([]byte{0xde, 0xad, 0, 0, 0xbe, 0xef}),
},
}
- require.Equal(t, opt.Length(), 10)
- require.Equal(t, opt.Code(), OptionClientID)
+ require.Equal(t, 10, opt.Length())
+ require.Equal(t, OptionClientID, opt.Code())
+ require.Contains(
+ t,
+ opt.String(),
+ "cid=DUID{type=DUID-LL hwtype=Ethernet hwaddr=de:ad:00:00:be:ef}",
+ "String() should contain the correct cid output",
+ )
+}
+
+func TestOptClientIdParseOptClientIdBogusDUID(t *testing.T) {
+ data := []byte{
+ 0, 4, // DUID_UUID
+ 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)
+ require.Error(t, err, "A truncated OptClientId DUID should return an error")
+}
+
+func TestOptClientIdParseOptClientIdInvalidTooShort(t *testing.T) {
+ data := []byte{
+ 0, // truncated: DUIDs are at least 2 bytes
+ }
+ _, err := ParseOptClientId(data)
+ require.Error(t, err, "A truncated OptClientId should return an error")
}
diff --git a/dhcpv6/option_dnsrecursivenameserver_test.go b/dhcpv6/option_dnsrecursivenameserver_test.go
index 71fe6d3..1a56797 100644
--- a/dhcpv6/option_dnsrecursivenameserver_test.go
+++ b/dhcpv6/option_dnsrecursivenameserver_test.go
@@ -16,8 +16,10 @@ func TestParseOptDNSRecursiveNameServer(t *testing.T) {
}
opt, err := ParseOptDNSRecursiveNameServer(data)
require.NoError(t, err)
- require.Equal(t, opt.NameServers, expected)
- require.Equal(t, opt.Length(), 16)
+ require.Equal(t, expected, opt.NameServers)
+ require.Equal(t, OptionDNSRecursiveNameServer, opt.Code())
+ require.Equal(t, 16, opt.Length())
+ require.Contains(t, opt.String(), "nameservers=[2a03:2880:fffe:c:face:b00c:0:35]", "String() should contain the correct nameservers output")
}
func TestOptDNSRecursiveNameServerToBytes(t *testing.T) {
@@ -31,5 +33,13 @@ func TestOptDNSRecursiveNameServerToBytes(t *testing.T) {
expected = append(expected, []byte(ns1)...)
expected = append(expected, []byte(ns2)...)
opt := OptDNSRecursiveNameServer{NameServers: nameservers}
- require.Equal(t, opt.ToBytes(), expected)
+ require.Equal(t, expected, opt.ToBytes())
+}
+
+func TestParseOptDNSRecursiveNameServerParseBogusNameserver(t *testing.T) {
+ data := []byte{
+ 0x2a, 0x03, 0x28, 0x80, 0xff, 0xfe, 0x00, 0x0c, // invalid IPv6 address
+ }
+ _, err := ParseOptDNSRecursiveNameServer(data)
+ require.Error(t, err, "An invalid nameserver IPv6 address should return an error")
}
diff --git a/dhcpv6/option_domainsearchlist_test.go b/dhcpv6/option_domainsearchlist_test.go
index 68f93ba..972a5bc 100644
--- a/dhcpv6/option_domainsearchlist_test.go
+++ b/dhcpv6/option_domainsearchlist_test.go
@@ -13,9 +13,11 @@ func TestParseOptDomainSearchList(t *testing.T) {
}
opt, err := ParseOptDomainSearchList(data)
require.NoError(t, err)
- require.Equal(t, len(opt.DomainSearchList), 2)
- require.Equal(t, opt.DomainSearchList[0], "example.com")
- require.Equal(t, opt.DomainSearchList[1], "subnet.example.org")
+ require.Equal(t, OptionDomainSearchList, opt.Code())
+ require.Equal(t, 2, len(opt.DomainSearchList))
+ require.Equal(t, "example.com", opt.DomainSearchList[0])
+ require.Equal(t, "subnet.example.org", opt.DomainSearchList[1])
+ require.Contains(t, opt.String(), "searchlist=[example.com subnet.example.org]", "String() should contain the correct domain search output")
}
func TestOptDomainSearchListToBytes(t *testing.T) {
@@ -31,5 +33,14 @@ func TestOptDomainSearchListToBytes(t *testing.T) {
"subnet.example.org",
},
}
- require.Equal(t, opt.ToBytes(), expected)
+ require.Equal(t, expected, opt.ToBytes())
+}
+
+func TestParseOptDomainSearchListInvalidLength(t *testing.T) {
+ data := []byte{
+ 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)
+ require.Error(t, err, "A truncated OptDomainSearchList should return an error")
}
diff --git a/dhcpv6/option_elapsedtime_test.go b/dhcpv6/option_elapsedtime_test.go
index 69e879c..d0d8e3f 100644
--- a/dhcpv6/option_elapsedtime_test.go
+++ b/dhcpv6/option_elapsedtime_test.go
@@ -3,6 +3,8 @@ package dhcpv6
import (
"bytes"
"testing"
+
+ "github.com/stretchr/testify/require"
)
func TestOptElapsedTime(t *testing.T) {
@@ -42,3 +44,11 @@ func TestOptElapsedTimeString(t *testing.T) {
t.Fatalf("Invalid elapsed time string. Expected %v, got %v", expected, optString)
}
}
+
+func TestOptElapsedTimeParseInvalidOption(t *testing.T) {
+ _, err := ParseOptElapsedTime([]byte{0xaa})
+ require.Error(t, err, "A short option should return an error")
+
+ _, err = ParseOptElapsedTime([]byte{0xaa, 0xbb, 0xcc})
+ require.Error(t, err, "An option with too many bytes should return an error")
+}
diff --git a/dhcpv6/option_iaaddress_test.go b/dhcpv6/option_iaaddress_test.go
index 0240949..dc6298d 100644
--- a/dhcpv6/option_iaaddress_test.go
+++ b/dhcpv6/option_iaaddress_test.go
@@ -67,3 +67,31 @@ func TestOptIAAddressToBytes(t *testing.T) {
}
require.Equal(t, expected, opt.ToBytes())
}
+
+func TestOptIAAddressString(t *testing.T) {
+ ipaddr := []byte{0x24, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
+ data := append(ipaddr, []byte{
+ 0xa, 0xb, 0xc, 0xd, // preferred lifetime
+ 0xe, 0xf, 0x1, 0x2, // valid lifetime
+ 0, 8, 0, 2, 0xaa, 0xbb, // options
+ }...)
+ opt, err := ParseOptIAAddress(data)
+ require.NoError(t, err)
+
+ str := opt.String()
+ require.Contains(
+ t, str,
+ "ipv6addr=2401:203:405:607:809:a0b:c0d:e0f",
+ "String() should return the ipv6addr",
+ )
+ require.Contains(
+ t, str,
+ "preferredlifetime=168496141",
+ "String() should return the preferredlifetime",
+ )
+ require.Contains(
+ t, str,
+ "validlifetime=235864322",
+ "String() should return the validlifetime",
+ )
+}
diff --git a/dhcpv6/option_iaprefix_test.go b/dhcpv6/option_iaprefix_test.go
index 0f37214..f7b5b6b 100644
--- a/dhcpv6/option_iaprefix_test.go
+++ b/dhcpv6/option_iaprefix_test.go
@@ -4,6 +4,8 @@ import (
"bytes"
"net"
"testing"
+
+ "github.com/stretchr/testify/require"
)
func TestOptIAPrefix(t *testing.T) {
@@ -62,3 +64,45 @@ func TestOptIAPrefixParseInvalidTooShort(t *testing.T) {
t.Fatalf("ParseOptIAPrefix: Expected error on truncated option, got %v", opt)
}
}
+
+func TestOptIAPrefixSetGetOptions(t *testing.T) {
+ opt := OptIAPrefix{
+ preferredLifetime: 0xaabbccdd,
+ validLifetime: 0xeeff0011,
+ }
+ expected := []byte{
+ 0, 8, 0, 2, 0xaa, 0xbb, // options
+ }
+
+ require.Equal(t, []byte(nil), opt.Options(), "Options() should be blank by default")
+ opt.SetOptions(expected)
+ require.Equal(t, expected, opt.Options(), "Options() did not contain the correct data")
+}
+
+func TestOptIAPrefixString(t *testing.T) {
+ buf := []byte{
+ 0xaa, 0xbb, 0xcc, 0xdd, // preferredLifetime
+ 0xee, 0xff, 0x00, 0x11, // validLifetime
+ 36, // prefixLength
+ 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ipv6Prefix
+ }
+ opt, err := ParseOptIAPrefix(buf)
+ require.NoError(t, err)
+
+ str := opt.String()
+ require.Contains(
+ t, str,
+ "ipv6prefix=2001:db8::",
+ "String() should return the ipv6addr",
+ )
+ require.Contains(
+ t, str,
+ "preferredlifetime=2864434397",
+ "String() should return the preferredlifetime",
+ )
+ require.Contains(
+ t, str,
+ "validlifetime=4009689105",
+ "String() should return the validlifetime",
+ )
+}
diff --git a/dhcpv6/option_interfaceid_test.go b/dhcpv6/option_interfaceid_test.go
index 21de822..b8c6b42 100644
--- a/dhcpv6/option_interfaceid_test.go
+++ b/dhcpv6/option_interfaceid_test.go
@@ -3,6 +3,8 @@ package dhcpv6
import (
"bytes"
"testing"
+
+ "github.com/stretchr/testify/require"
)
func TestOptInterfaceId(t *testing.T) {
@@ -23,11 +25,22 @@ func TestOptInterfaceIdToBytes(t *testing.T) {
interfaceId := []byte("DSLAM01 eth2/1/01/21")
expected := []byte{00, 18, 00, byte(len(interfaceId))}
expected = append(expected, interfaceId...)
- opt := OptInterfaceId{
- interfaceId: interfaceId,
- }
+ opt := OptInterfaceId{}
+ opt.SetInterfaceID(interfaceId)
toBytes := opt.ToBytes()
if !bytes.Equal(toBytes, expected) {
t.Fatalf("Invalid ToBytes result. Expected %v, got %v", expected, toBytes)
}
}
+
+func TestOptInterfaceIdString(t *testing.T) {
+ interfaceId := []byte("DSLAM01 eth2/1/01/21")
+ opt := OptInterfaceId{}
+ opt.SetInterfaceID(interfaceId)
+ require.Contains(
+ t,
+ opt.String(),
+ "68 83 76 65 77 48 49 32 101 116 104 50 47 49 47 48 49 47 50 49",
+ "String() should return the interfaceId as bytes",
+ )
+}
diff --git a/dhcpv6/option_nii_test.go b/dhcpv6/option_nii_test.go
new file mode 100644
index 0000000..190c0e3
--- /dev/null
+++ b/dhcpv6/option_nii_test.go
@@ -0,0 +1,70 @@
+package dhcpv6
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestOptNetworkInterfaceIdParse(t *testing.T) {
+ expected := []byte{
+ 1, // type (UNDI)
+ 3, // major revision
+ 20, // minor revision
+ }
+ opt, err := ParseOptNetworkInterfaceId(expected)
+ require.NoError(t, err, "ParseOptNetworkInterfaceId() should not return an error with correct bytes")
+ require.Equal(t, 3, opt.Length(), "Length() should return 3")
+ require.Equal(t, OptionNII, opt.Code(), OptionNII, "Code() should return 62 for OptNetworkInterfaceId")
+ require.Equal(t, uint8(1), opt.Type(), "Type() should return 1 for UNDI")
+ require.Equal(t, uint8(3), opt.Major(), "Major() should return 1 for UNDI")
+ require.Equal(t, uint8(20), opt.Minor(), "Minor() should return 1 for UNDI")
+}
+
+func TestOptNetworkInterfaceIdToBytes(t *testing.T) {
+ expected := []byte{
+ 0, 62, // OptNetworkInterfaceId
+ 0, 3, // length
+ 1, // type (UNDI)
+ 3, // major revision
+ 20, // minor revision
+ }
+ opt := OptNetworkInterfaceId{}
+ opt.SetType(1)
+ opt.SetMajor(3)
+ opt.SetMinor(20)
+ require.Equal(t, expected, opt.ToBytes())
+}
+
+func TestOptNetworkInterfaceIdTooShort(t *testing.T) {
+ buf := []byte{
+ 0, 62, // OptNetworkInterfaceId
+ 0, 3, // length
+ 1, // type (UNDI)
+ // missing major/minor revision bytes
+ }
+ _, err := ParseOptNetworkInterfaceId(buf)
+ require.Error(t, err, "ParseOptNetworkInterfaceId() should return an error on truncated options")
+}
+
+func TestOptNetworkInterfaceIdString(t *testing.T) {
+ buf := []byte{
+ 1, // type (UNDI)
+ 3, // major revision
+ 20, // minor revision
+ }
+ opt, err := ParseOptNetworkInterfaceId(buf)
+ require.NoError(t, err)
+ require.Contains(
+ t,
+ opt.String(),
+ "type=First gen. PXE boot ROMs, revision=3.20",
+ "String() should contain the type and revision",
+ )
+ opt.SetType(200)
+ require.Contains(
+ t, opt.String(),
+ "type=Unknown",
+ "String() should contain unknown for an unknown type",
+ )
+}
diff --git a/dhcpv6/option_nontemporaryaddress_test.go b/dhcpv6/option_nontemporaryaddress_test.go
index 39c3c36..9edf521 100644
--- a/dhcpv6/option_nontemporaryaddress_test.go
+++ b/dhcpv6/option_nontemporaryaddress_test.go
@@ -17,6 +17,7 @@ func TestOptIANAParseOptIANA(t *testing.T) {
opt, err := ParseOptIANA(data)
require.NoError(t, err)
require.Equal(t, len(data), opt.Length())
+ require.Equal(t, OptionIANA, opt.Code())
}
func TestOptIANAParseOptIANAInvalidLength(t *testing.T) {
@@ -100,3 +101,31 @@ func TestOptIANAToBytes(t *testing.T) {
}
require.Equal(t, expected, opt.ToBytes())
}
+
+func TestOptIANAString(t *testing.T) {
+ data := []byte{
+ 1, 0, 0, 0, // IAID
+ 0, 0, 0, 1, // T1
+ 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)
+ require.NoError(t, err)
+
+ str := opt.String()
+ require.Contains(
+ t, str,
+ "IAID=[1 0 0 0]",
+ "String() should return the IAID",
+ )
+ require.Contains(
+ t, str,
+ "t1=1, t2=2",
+ "String() should return the T1/T2 options",
+ )
+ require.Contains(
+ t, str,
+ "options=[",
+ "String() should return a list of options",
+ )
+}
diff --git a/dhcpv6/option_prefixdelegation_test.go b/dhcpv6/option_prefixdelegation_test.go
index caedd40..bf84038 100644
--- a/dhcpv6/option_prefixdelegation_test.go
+++ b/dhcpv6/option_prefixdelegation_test.go
@@ -20,6 +20,10 @@ func TestOptIAForPrefixDelegationParseOptIAForPrefixDelegation(t *testing.T) {
opt, err := ParseOptIAForPrefixDelegation(data)
require.NoError(t, err)
require.Equal(t, len(data), opt.Length())
+ require.Equal(t, OptionIAPD, opt.Code())
+ require.Equal(t, []byte{1, 0, 0, 0}, opt.IAID())
+ require.Equal(t, uint32(1), opt.T1())
+ require.Equal(t, uint32(2), opt.T2())
}
func TestOptIAForPrefixDelegationParseOptIAForPrefixDelegationInvalidLength(t *testing.T) {
@@ -110,12 +114,12 @@ func TestOptIAForPrefixDelegationToBytes(t *testing.T) {
oaddr.SetPrefixLength(36)
oaddr.SetIPv6Prefix([16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
- opt := OptIAForPrefixDelegation{
- iaId: [4]byte{1, 2, 3, 4},
- t1: 12345,
- t2: 54321,
- }
+ opt := OptIAForPrefixDelegation{}
+ opt.SetIAID([4]byte{1, 2, 3, 4})
+ opt.SetT1(12345)
+ opt.SetT2(54321)
opt.SetOptions(oaddr.ToBytes())
+
expected := []byte{
0, 25, // OptionIAPD
0, 41, // length
@@ -130,3 +134,47 @@ func TestOptIAForPrefixDelegationToBytes(t *testing.T) {
}
require.Equal(t, expected, opt.ToBytes())
}
+
+func TestOptIAForPrefixDelegationSetOptionsTooShort(t *testing.T) {
+ buf := []byte{
+ 0, 26, 0, 25, // 26 = IAPrefix Option, 25 = length
+ 0xaa, 0xbb, 0xcc, 0xdd, // IAPrefix preferredLifetime
+ 0xee, 0xff, // truncated half-way through validLifetime
+ }
+
+ oaddr := OptIAForPrefixDelegation{}
+ err := oaddr.SetOptions(buf)
+ require.Error(t, err, "SetOptions() should return an error if invalid options are set")
+}
+
+func TestOptIAForPrefixDelegationString(t *testing.T) {
+ data := []byte{
+ 1, 0, 0, 0, // IAID
+ 0, 0, 0, 1, // T1
+ 0, 0, 0, 2, // T2
+ 0, 26, 0, 25, // 26 = IAPrefix Option, 25 = length
+ 0xaa, 0xbb, 0xcc, 0xdd, // IAPrefix preferredLifetime
+ 0xee, 0xff, 0x00, 0x11, // IAPrefix validLifetime
+ 36, // IAPrefix prefixLength
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // IAPrefix ipv6Prefix
+ }
+ opt, err := ParseOptIAForPrefixDelegation(data)
+ require.NoError(t, err)
+
+ str := opt.String()
+ require.Contains(
+ t, str,
+ "IAID=[1 0 0 0]",
+ "String() should return the IAID",
+ )
+ require.Contains(
+ t, str,
+ "t1=1, t2=2",
+ "String() should return the T1/T2 options",
+ )
+ require.Contains(
+ t, str,
+ "options=[",
+ "String() should return a list of options",
+ )
+}
diff --git a/dhcpv6/option_relaymsg_test.go b/dhcpv6/option_relaymsg_test.go
index df2442c..15d869a 100644
--- a/dhcpv6/option_relaymsg_test.go
+++ b/dhcpv6/option_relaymsg_test.go
@@ -3,6 +3,8 @@ package dhcpv6
import (
"reflect"
"testing"
+
+ "github.com/stretchr/testify/require"
)
func TestRelayMsgParseOptRelayMsg(t *testing.T) {
@@ -155,3 +157,30 @@ func TestSample(t *testing.T) {
t.Fatal(err)
}
}
+
+func TestRelayMsgParseOptRelayMsgTooShort(t *testing.T) {
+ _, err := ParseOptRelayMsg([]byte{
+ 1, // MessageTypeSolicit
+ 0xaa, 0xbb, 0xcc, // transaction ID
+ 0, 8, // option: elapsed time
+ // no length/value for elapsed time option
+ })
+ require.Error(t, err, "ParseOptRelayMsg() should return an error if the encapsulated message is invalid")
+}
+
+func TestRelayMsgString(t *testing.T) {
+ opt, err := ParseOptRelayMsg([]byte{
+ 1, // MessageTypeSolicit
+ 0xaa, 0xbb, 0xcc, // transaction ID
+ 0, 8, // option: elapsed time
+ 0, 2, // option length
+ 0, 0, // option value
+ })
+ require.NoError(t, err)
+ require.Contains(
+ t,
+ opt.String(),
+ "relaymsg=DHCPv6Message",
+ "String() should contain the relaymsg contents",
+ )
+}
diff --git a/dhcpv6/option_remoteid_test.go b/dhcpv6/option_remoteid_test.go
index b2ef3cc..bc13d43 100644
--- a/dhcpv6/option_remoteid_test.go
+++ b/dhcpv6/option_remoteid_test.go
@@ -3,6 +3,8 @@ package dhcpv6
import (
"bytes"
"testing"
+
+ "github.com/stretchr/testify/require"
)
func TestOptRemoteId(t *testing.T) {
@@ -36,3 +38,42 @@ func TestOptRemoteIdToBytes(t *testing.T) {
t.Fatalf("Invalid ToBytes result. Expected %v, got %v", expected, toBytes)
}
}
+
+func TestOptRemoteIdSet(t *testing.T) {
+ enterpriseNumber := uint32(12345)
+ remoteID := []byte("DSLAM01 eth2/1/01/21")
+ opt := OptRemoteId{}
+ opt.SetEnterpriseNumber(enterpriseNumber)
+ opt.SetRemoteID(remoteID)
+
+ require.Equal(t, uint32(12345), opt.EnterpriseNumber())
+ require.Equal(t, []byte("DSLAM01 eth2/1/01/21"), opt.RemoteID())
+}
+
+func TestOptRemoteIdParseOptRemoteIdTooShort(t *testing.T) {
+ buf := []byte{0xaa, 0xbb, 0xcc}
+ _, err := ParseOptRemoteId(buf)
+ require.Error(t, err, "A short option should return an error")
+}
+
+func TestOptRemoteIdString(t *testing.T) {
+ buf := []byte{0xaa, 0xbb, 0xcc, 0xdd}
+ remoteId := []byte("Test1234")
+ buf = append(buf, remoteId...)
+
+ opt, err := ParseOptRemoteId(buf)
+ require.NoError(t, err)
+ str := opt.String()
+ require.Contains(
+ t,
+ str,
+ "enterprisenum=2864434397",
+ "String() should contain the enterprisenum",
+ )
+ require.Contains(
+ t,
+ str,
+ "remoteid=[84 101 115 116 49 50 51 52]",
+ "String() should contain the remoteid bytes",
+ )
+}
diff --git a/dhcpv6/option_requestedoption_test.go b/dhcpv6/option_requestedoption_test.go
new file mode 100644
index 0000000..7e95e36
--- /dev/null
+++ b/dhcpv6/option_requestedoption_test.go
@@ -0,0 +1,38 @@
+package dhcpv6
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestOptRequestedOption(t *testing.T) {
+ expected := []byte{0, 1, 0, 2}
+ _, err := ParseOptRequestedOption(expected)
+ require.NoError(t, err, "ParseOptRequestedOption() correct options should not error")
+}
+
+func TestOptRequestedOptionParseOptRequestedOptionTooShort(t *testing.T) {
+ buf := []byte{0, 1, 0}
+ _, err := ParseOptRequestedOption(buf)
+ require.Error(t, err, "A short option should return an error (must be divisible by 2)")
+}
+
+func TestOptRequestedOptionString(t *testing.T) {
+ buf := []byte{0, 1, 0, 2}
+ opt, err := ParseOptRequestedOption(buf)
+ require.NoError(t, err)
+ require.Contains(
+ t,
+ opt.String(),
+ "OPTION_CLIENTID, OPTION_SERVERID",
+ "String() should contain the options specified",
+ )
+ opt.AddRequestedOption(12345)
+ require.Contains(
+ t,
+ opt.String(),
+ "Unknown",
+ "String() should contain 'Unknown' for an illegal option",
+ )
+}
diff --git a/dhcpv6/option_serverid_test.go b/dhcpv6/option_serverid_test.go
index e330fa8..44f6cf4 100644
--- a/dhcpv6/option_serverid_test.go
+++ b/dhcpv6/option_serverid_test.go
@@ -16,9 +16,9 @@ func TestParseOptServerId(t *testing.T) {
}
opt, err := ParseOptServerId(data)
require.NoError(t, err)
- require.Equal(t, opt.Sid.Type, DUID_LL)
- require.Equal(t, opt.Sid.HwType, iana.HwTypeEthernet)
- require.Equal(t, opt.Sid.LinkLayerAddr, net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5}))
+ require.Equal(t, DUID_LL, opt.Sid.Type)
+ require.Equal(t, iana.HwTypeEthernet, opt.Sid.HwType)
+ require.Equal(t, net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5}), opt.Sid.LinkLayerAddr)
}
func TestOptServerIdToBytes(t *testing.T) {
@@ -62,6 +62,30 @@ func TestOptionServerId(t *testing.T) {
LinkLayerAddr: net.HardwareAddr([]byte{0xde, 0xad, 0, 0, 0xbe, 0xef}),
},
}
- require.Equal(t, opt.Length(), 10)
- require.Equal(t, opt.Code(), OptionServerID)
+ require.Equal(t, 10, opt.Length())
+ require.Equal(t, OptionServerID, opt.Code())
+ require.Contains(
+ t,
+ opt.String(),
+ "sid=DUID{type=DUID-LL hwtype=Ethernet hwaddr=de:ad:00:00:be:ef}",
+ "String() should contain the correct sid output",
+ )
+}
+
+func TestOptServerIdParseOptServerIdBogusDUID(t *testing.T) {
+ data := []byte{
+ 0, 4, // DUID_UUID
+ 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)
+ require.Error(t, err, "A truncated OptServerId DUID should return an error")
+}
+
+func TestOptServerIdParseOptServerIdInvalidTooShort(t *testing.T) {
+ data := []byte{
+ 0, // truncated: DUIDs are at least 2 bytes
+ }
+ _, err := ParseOptServerId(data)
+ require.Error(t, err, "A truncated OptServerId should return an error")
}
diff --git a/dhcpv6/option_statuscode_test.go b/dhcpv6/option_statuscode_test.go
index 6d2ba94..a2cce0f 100644
--- a/dhcpv6/option_statuscode_test.go
+++ b/dhcpv6/option_statuscode_test.go
@@ -14,8 +14,8 @@ func TestParseOptStatusCode(t *testing.T) {
}
opt, err := ParseOptStatusCode(data)
require.NoError(t, err)
- require.Equal(t, opt.StatusCode, iana.StatusUseMulticast)
- require.Equal(t, opt.StatusMessage, []byte("use multicast"))
+ require.Equal(t, iana.StatusUseMulticast, opt.StatusCode)
+ require.Equal(t, []byte("use multicast"), opt.StatusMessage)
}
func TestOptStatusCodeToBytes(t *testing.T) {
@@ -32,3 +32,24 @@ func TestOptStatusCodeToBytes(t *testing.T) {
actual := opt.ToBytes()
require.Equal(t, expected, actual)
}
+
+func TestOptStatusCodeParseOptStatusCodeTooShort(t *testing.T) {
+ _, err := ParseOptStatusCode([]byte{0})
+ require.Error(t, err, "ParseOptStatusCode: Expected error on truncated option")
+}
+
+func TestOptStatusCodeString(t *testing.T) {
+ data := []byte{
+ 0, 5, // StatusUseMulticast
+ 'u', 's', 'e', ' ', 'm', 'u', 'l', 't', 'i', 'c', 'a', 's', 't',
+ }
+ opt, err := ParseOptStatusCode(data)
+ require.NoError(t, err)
+
+ require.Contains(
+ t,
+ opt.String(),
+ "code=UseMulticast (5), message=use multicast",
+ "String() should contain the code and message",
+ )
+}
diff --git a/dhcpv6/option_userclass_test.go b/dhcpv6/option_userclass_test.go
index 3ba65cf..8a03319 100644
--- a/dhcpv6/option_userclass_test.go
+++ b/dhcpv6/option_userclass_test.go
@@ -63,3 +63,35 @@ func TestOptUserClassToBytesMultiple(t *testing.T) {
}
require.Equal(t, expected, data)
}
+
+func TestOptUserClassParseOptUserClassTooShort(t *testing.T) {
+ buf := []byte{
+ 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't',
+ 0, 4, 't', 'e',
+ }
+ _, err := ParseOptUserClass(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)
+ require.Error(t, err, "ParseOptUserClass() should error if given a truncated length")
+}
+
+func TestOptUserClassString(t *testing.T) {
+ data := []byte{
+ 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't',
+ 0, 4, 't', 'e', 's', 't',
+ }
+ opt, err := ParseOptUserClass(data)
+ require.NoError(t, err)
+
+ require.Contains(
+ t,
+ opt.String(),
+ "userclass=[linuxboot, test]",
+ "String() should contain the list of user classes",
+ )
+}
diff --git a/dhcpv6/option_vendorclass_test.go b/dhcpv6/option_vendorclass_test.go
index 0db278f..7774b25 100644
--- a/dhcpv6/option_vendorclass_test.go
+++ b/dhcpv6/option_vendorclass_test.go
@@ -14,8 +14,9 @@ func TestParseOptVendorClass(t *testing.T) {
}
opt, err := ParseOptVendorClass(data)
require.NoError(t, err)
- require.Equal(t, len(opt.Data), 2)
- require.Equal(t, opt.EnterpriseNumber, uint32(0xaabbccdd))
+ require.Equal(t, OptionVendorClass, opt.Code())
+ require.Equal(t, 2, len(opt.Data))
+ require.Equal(t, uint32(0xaabbccdd), opt.EnterpriseNumber)
require.Equal(t, []byte("HTTPClient"), opt.Data[0])
require.Equal(t, []byte("test"), opt.Data[1])
}
@@ -38,3 +39,57 @@ func TestOptVendorClassToBytes(t *testing.T) {
}
require.Equal(t, expected, data)
}
+
+func TestOptVendorClassParseOptVendorClassMalformed(t *testing.T) {
+ buf := []byte{
+ 0xaa, 0xbb, // truncated EnterpriseNumber
+ }
+ _, err := ParseOptVendorClass(buf)
+ require.Error(t, err, "ParseOptVendorClass() should error if given truncated EnterpriseNumber")
+
+ buf = []byte{
+ 0xaa, 0xbb, 0xcc, 0xdd, // EnterpriseNumber
+ }
+ _, err = ParseOptVendorClass(buf)
+ require.Error(t, err, "ParseOptVendorClass() should error if given no vendor classes")
+
+ buf = []byte{
+ 0xaa, 0xbb, 0xcc, 0xdd, // EnterpriseNumber
+ 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't',
+ 0, 4, 't', 'e',
+ }
+ _, err = ParseOptVendorClass(buf)
+ require.Error(t, err, "ParseOptVendorClass() should error if given truncated vendor classes")
+
+ buf = []byte{
+ 0xaa, 0xbb, 0xcc, 0xdd, // EnterpriseNumber
+ 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't',
+ 0,
+ }
+ _, err = ParseOptVendorClass(buf)
+ require.Error(t, err, "ParseOptVendorClass() should error if given a truncated length")
+}
+
+func TestOptVendorClassString(t *testing.T) {
+ data := []byte{
+ 0xaa, 0xbb, 0xcc, 0xdd, // EnterpriseNumber
+ 0, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't',
+ 0, 4, 't', 'e', 's', 't',
+ }
+ opt, err := ParseOptVendorClass(data)
+ require.NoError(t, err)
+
+ str := opt.String()
+ require.Contains(
+ t,
+ str,
+ "enterprisenum=2864434397",
+ "String() should contain the enterprisenum",
+ )
+ require.Contains(
+ t,
+ str,
+ "data=[linuxboot, test]",
+ "String() should contain the list of vendor classes",
+ )
+}