diff options
Diffstat (limited to 'dhcpv4/options_test.go')
-rw-r--r-- | dhcpv4/options_test.go | 163 |
1 files changed, 130 insertions, 33 deletions
diff --git a/dhcpv4/options_test.go b/dhcpv4/options_test.go index 2557af5..9a2f1c0 100644 --- a/dhcpv4/options_test.go +++ b/dhcpv4/options_test.go @@ -1,6 +1,9 @@ package dhcpv4 import ( + "bytes" + "fmt" + "math" "testing" "github.com/stretchr/testify/require" @@ -9,7 +12,7 @@ import ( func TestParseOption(t *testing.T) { // Generic option := []byte{5, 4, 192, 168, 1, 254} // DNS option - opt, err := ParseOption(option) + opt, err := ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) generic := opt.(*OptionGeneric) require.Equal(t, OptionNameServer, generic.Code()) @@ -19,7 +22,7 @@ func TestParseOption(t *testing.T) { // Option subnet mask option = []byte{1, 4, 255, 255, 255, 0} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionSubnetMask, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -27,7 +30,7 @@ func TestParseOption(t *testing.T) { // Option router option = []byte{3, 4, 192, 168, 1, 1} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionRouter, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -35,7 +38,7 @@ func TestParseOption(t *testing.T) { // Option domain name server option = []byte{6, 4, 192, 168, 1, 1} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionDomainNameServer, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -43,7 +46,7 @@ func TestParseOption(t *testing.T) { // Option host name option = []byte{12, 4, 't', 'e', 's', 't'} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionHostName, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -51,7 +54,7 @@ func TestParseOption(t *testing.T) { // Option domain name option = []byte{15, 4, 't', 'e', 's', 't'} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionDomainName, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -59,7 +62,7 @@ func TestParseOption(t *testing.T) { // Option root path option = []byte{17, 4, '/', 'f', 'o', 'o'} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionRootPath, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -67,7 +70,7 @@ func TestParseOption(t *testing.T) { // Option broadcast address option = []byte{28, 4, 255, 255, 255, 255} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionBroadcastAddress, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -75,7 +78,7 @@ func TestParseOption(t *testing.T) { // Option NTP servers option = []byte{42, 4, 10, 10, 10, 10} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionNTPServers, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -83,7 +86,7 @@ func TestParseOption(t *testing.T) { // Requested IP address option = []byte{50, 4, 1, 2, 3, 4} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionRequestedIPAddress, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -91,7 +94,7 @@ func TestParseOption(t *testing.T) { // Requested IP address lease time option = []byte{51, 4, 0, 0, 0, 0} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionIPAddressLeaseTime, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -99,7 +102,7 @@ func TestParseOption(t *testing.T) { // Message type option = []byte{53, 1, 1} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionDHCPMessageType, opt.Code(), "Code") require.Equal(t, 1, opt.Length(), "Length") @@ -107,7 +110,7 @@ func TestParseOption(t *testing.T) { // Option server ID option = []byte{54, 4, 1, 2, 3, 4} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionServerIdentifier, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -115,7 +118,7 @@ func TestParseOption(t *testing.T) { // Parameter request list option = []byte{55, 3, 5, 53, 61} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionParameterRequestList, opt.Code(), "Code") require.Equal(t, 3, opt.Length(), "Length") @@ -123,7 +126,7 @@ func TestParseOption(t *testing.T) { // Option max message size option = []byte{57, 2, 1, 2} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionMaximumDHCPMessageSize, opt.Code(), "Code") require.Equal(t, 2, opt.Length(), "Length") @@ -131,7 +134,7 @@ func TestParseOption(t *testing.T) { // Option class identifier option = []byte{60, 4, 't', 'e', 's', 't'} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionClassIdentifier, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -139,7 +142,7 @@ func TestParseOption(t *testing.T) { // Option TFTP server name option = []byte{66, 4, 't', 'e', 's', 't'} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionTFTPServerName, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") @@ -147,7 +150,7 @@ func TestParseOption(t *testing.T) { // Option Bootfile name option = []byte{67, 9, 'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't'} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionBootfileName, opt.Code(), "Code") require.Equal(t, 9, opt.Length(), "Length") @@ -155,37 +158,131 @@ func TestParseOption(t *testing.T) { // Option user class information option = []byte{77, 5, 4, 't', 'e', 's', 't'} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionUserClassInformation, opt.Code(), "Code") require.Equal(t, 5, opt.Length(), "Length") require.Equal(t, option, opt.ToBytes(), "ToBytes") // Option relay agent information - option = []byte{82, 2, 1, 0} - opt, err = ParseOption(option) + option = []byte{82, 6, 1, 4, 129, 168, 0, 1} + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionRelayAgentInformation, opt.Code(), "Code") - require.Equal(t, 2, opt.Length(), "Length") + require.Equal(t, 6, opt.Length(), "Length") require.Equal(t, option, opt.ToBytes(), "ToBytes") // Option client system architecture type option option = []byte{93, 4, 't', 'e', 's', 't'} - opt, err = ParseOption(option) + opt, err = ParseOption(OptionCode(option[0]), option[2:]) require.NoError(t, err) require.Equal(t, OptionClientSystemArchitectureType, opt.Code(), "Code") require.Equal(t, 4, opt.Length(), "Length") require.Equal(t, option, opt.ToBytes(), "ToBytes") } -func TestParseOptionZeroLength(t *testing.T) { - option := []byte{} - _, err := ParseOption(option) - require.Error(t, err, "should get error from zero-length options") -} - -func TestParseOptionShortOption(t *testing.T) { - option := []byte{53, 1} - _, err := ParseOption(option) - require.Error(t, err, "should get error from short options") +func TestOptionsUnmarshal(t *testing.T) { + for i, tt := range []struct { + input []byte + want Options + wantError bool + }{ + { + // Buffer missing data. + input: []byte{ + 3 /* key */, 3 /* length */, 1, + }, + wantError: true, + }, + { + input: []byte{ + // This may look too long, but 0 is padding. + // The issue here is the missing OptionEnd. + 3, 3, 0, 0, 0, 0, 0, 0, 0, + }, + wantError: true, + }, + { + // Only OptionPad and OptionEnd can stand on their own + // without a length field. So this is too short. + input: []byte{ + 3, + }, + wantError: true, + }, + { + // Option present after the End is a nono. + input: []byte{byte(OptionEnd), 3}, + wantError: true, + }, + { + input: []byte{byte(OptionEnd)}, + want: Options{}, + }, + { + input: []byte{ + 3, 2, 5, 6, + byte(OptionEnd), + }, + want: Options{ + &OptionGeneric{ + OptionCode: 3, + Data: []byte{5, 6}, + }, + }, + }, + { + // Test RFC 3396. + input: append( + append([]byte{3, math.MaxUint8}, bytes.Repeat([]byte{10}, math.MaxUint8)...), + 3, 5, 10, 10, 10, 10, 10, + byte(OptionEnd), + ), + want: Options{ + &OptionGeneric{ + OptionCode: 3, + Data: bytes.Repeat([]byte{10}, math.MaxUint8+5), + }, + }, + }, + { + input: []byte{ + 10, 2, 255, 254, + 11, 3, 5, 5, 5, + byte(OptionEnd), + }, + want: Options{ + &OptionGeneric{ + OptionCode: 10, + Data: []byte{255, 254}, + }, + &OptionGeneric{ + OptionCode: 11, + Data: []byte{5, 5, 5}, + }, + }, + }, + { + input: append( + append([]byte{10, 2, 255, 254}, bytes.Repeat([]byte{byte(OptionPad)}, 255)...), + byte(OptionEnd), + ), + want: Options{ + &OptionGeneric{ + OptionCode: 10, + Data: []byte{255, 254}, + }, + }, + }, + } { + t.Run(fmt.Sprintf("Test %02d", i), func(t *testing.T) { + opt, err := OptionsFromBytesWithParser(tt.input, ParseOptionGeneric, true) + if tt.wantError { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, opt, tt.want) + } + }) + } } |