diff options
author | David Barr <38654497+davebarrau@users.noreply.github.com> | 2018-10-12 11:09:04 +1100 |
---|---|---|
committer | insomniac <insomniacslk@users.noreply.github.com> | 2018-10-11 17:09:04 -0700 |
commit | dc01165c86340093eacf62c0856ae4e2164a4845 (patch) | |
tree | 9ca76ae4103c3e63cd86620fdec230e5cfe5b78d /dhcpv6 | |
parent | ee671d361777cc640550bab38cc6b0d412396f80 (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.go | 9 | ||||
-rw-r--r-- | dhcpv6/option_bootfileurl_test.go | 3 | ||||
-rw-r--r-- | dhcpv6/option_clientid_test.go | 34 | ||||
-rw-r--r-- | dhcpv6/option_dnsrecursivenameserver_test.go | 16 | ||||
-rw-r--r-- | dhcpv6/option_domainsearchlist_test.go | 19 | ||||
-rw-r--r-- | dhcpv6/option_elapsedtime_test.go | 10 | ||||
-rw-r--r-- | dhcpv6/option_iaaddress_test.go | 28 | ||||
-rw-r--r-- | dhcpv6/option_iaprefix_test.go | 44 | ||||
-rw-r--r-- | dhcpv6/option_interfaceid_test.go | 19 | ||||
-rw-r--r-- | dhcpv6/option_nii_test.go | 70 | ||||
-rw-r--r-- | dhcpv6/option_nontemporaryaddress_test.go | 29 | ||||
-rw-r--r-- | dhcpv6/option_prefixdelegation_test.go | 58 | ||||
-rw-r--r-- | dhcpv6/option_relaymsg_test.go | 29 | ||||
-rw-r--r-- | dhcpv6/option_remoteid_test.go | 41 | ||||
-rw-r--r-- | dhcpv6/option_requestedoption_test.go | 38 | ||||
-rw-r--r-- | dhcpv6/option_serverid_test.go | 34 | ||||
-rw-r--r-- | dhcpv6/option_statuscode_test.go | 25 | ||||
-rw-r--r-- | dhcpv6/option_userclass_test.go | 32 | ||||
-rw-r--r-- | dhcpv6/option_vendorclass_test.go | 59 |
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", + ) +} |