summaryrefslogtreecommitdiffhomepage
path: root/dhcpv4/options_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'dhcpv4/options_test.go')
-rw-r--r--dhcpv4/options_test.go333
1 files changed, 151 insertions, 182 deletions
diff --git a/dhcpv4/options_test.go b/dhcpv4/options_test.go
index 0c1c1fa..6c5393c 100644
--- a/dhcpv4/options_test.go
+++ b/dhcpv4/options_test.go
@@ -11,154 +11,148 @@ import (
)
func TestParseOption(t *testing.T) {
- // Generic
- option := []byte{192, 168, 1, 254} // Name server option
- opt, err := ParseOption(OptionNameServer, option)
- require.NoError(t, err)
- generic := opt.(*OptionGeneric)
- require.Equal(t, OptionNameServer, generic.Code())
- require.Equal(t, []byte{192, 168, 1, 254}, generic.Data)
- require.Equal(t, "Name Server -> [192 168 1 254]", generic.String())
-
- // Option subnet mask
- option = []byte{255, 255, 255, 0}
- opt, err = ParseOption(OptionSubnetMask, option)
- require.NoError(t, err)
- require.Equal(t, OptionSubnetMask, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Option router
- option = []byte{192, 168, 1, 1}
- opt, err = ParseOption(OptionRouter, option)
- require.NoError(t, err)
- require.Equal(t, OptionRouter, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Option domain name server
- option = []byte{192, 168, 1, 1}
- opt, err = ParseOption(OptionDomainNameServer, option)
- require.NoError(t, err)
- require.Equal(t, OptionDomainNameServer, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Option host name
- option = []byte{'t', 'e', 's', 't'}
- opt, err = ParseOption(OptionHostName, option)
- require.NoError(t, err)
- require.Equal(t, OptionHostName, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Option domain name
- option = []byte{'t', 'e', 's', 't'}
- opt, err = ParseOption(OptionDomainName, option)
- require.NoError(t, err)
- require.Equal(t, OptionDomainName, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Option root path
- option = []byte{'/', 'f', 'o', 'o'}
- opt, err = ParseOption(OptionRootPath, option)
- require.NoError(t, err)
- require.Equal(t, OptionRootPath, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Option broadcast address
- option = []byte{255, 255, 255, 255}
- opt, err = ParseOption(OptionBroadcastAddress, option)
- require.NoError(t, err)
- require.Equal(t, OptionBroadcastAddress, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Option NTP servers
- option = []byte{10, 10, 10, 10}
- opt, err = ParseOption(OptionNTPServers, option)
- require.NoError(t, err)
- require.Equal(t, OptionNTPServers, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Requested IP address
- option = []byte{1, 2, 3, 4}
- opt, err = ParseOption(OptionRequestedIPAddress, option)
- require.NoError(t, err)
- require.Equal(t, OptionRequestedIPAddress, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Requested IP address lease time
- option = []byte{0, 0, 0, 0}
- opt, err = ParseOption(OptionIPAddressLeaseTime, option)
- require.NoError(t, err)
- require.Equal(t, OptionIPAddressLeaseTime, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Message type
- option = []byte{1}
- opt, err = ParseOption(OptionDHCPMessageType, option)
- require.NoError(t, err)
- require.Equal(t, OptionDHCPMessageType, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Option server ID
- option = []byte{1, 2, 3, 4}
- opt, err = ParseOption(OptionServerIdentifier, option)
- require.NoError(t, err)
- require.Equal(t, OptionServerIdentifier, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Parameter request list
- option = []byte{5, 53, 61}
- opt, err = ParseOption(OptionParameterRequestList, option)
- require.NoError(t, err)
- require.Equal(t, OptionParameterRequestList, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Option max message size
- option = []byte{1, 2}
- opt, err = ParseOption(OptionMaximumDHCPMessageSize, option)
- require.NoError(t, err)
- require.Equal(t, OptionMaximumDHCPMessageSize, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Option class identifier
- option = []byte{'t', 'e', 's', 't'}
- opt, err = ParseOption(OptionClassIdentifier, option)
- require.NoError(t, err)
- require.Equal(t, OptionClassIdentifier, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Option TFTP server name
- option = []byte{'t', 'e', 's', 't'}
- opt, err = ParseOption(OptionTFTPServerName, option)
- require.NoError(t, err)
- require.Equal(t, OptionTFTPServerName, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
-
- // Option Bootfile name
- option = []byte{'l', 'i', 'n', 'u', 'x', 'b', 'o', 'o', 't'}
- opt, err = ParseOption(OptionBootfileName, option)
- require.NoError(t, err)
- require.Equal(t, OptionBootfileName, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
+ for _, tt := range []struct {
+ code OptionCode
+ value []byte
+ want string
+ }{
+ {
+ code: OptionNameServer,
+ value: []byte{192, 168, 1, 254},
+ want: "[192 168 1 254]",
+ },
+ {
+ code: OptionSubnetMask,
+ value: []byte{255, 255, 255, 0},
+ want: "ffffff00",
+ },
+ {
+ code: OptionRouter,
+ value: []byte{192, 168, 1, 1, 192, 168, 2, 1},
+ want: "192.168.1.1, 192.168.2.1",
+ },
+ {
+ code: OptionDomainNameServer,
+ value: []byte{192, 168, 1, 1, 192, 168, 2, 1},
+ want: "192.168.1.1, 192.168.2.1",
+ },
+ {
+ code: OptionNTPServers,
+ value: []byte{192, 168, 1, 1, 192, 168, 2, 1},
+ want: "192.168.1.1, 192.168.2.1",
+ },
+ {
+ code: OptionServerIdentifier,
+ value: []byte{192, 168, 1, 1, 192, 168, 2, 1},
+ want: "192.168.1.1, 192.168.2.1",
+ },
+ {
+ code: OptionHostName,
+ value: []byte("test"),
+ want: "test",
+ },
+ {
+ code: OptionDomainName,
+ value: []byte("test"),
+ want: "test",
+ },
+ {
+ code: OptionRootPath,
+ value: []byte("test"),
+ want: "test",
+ },
+ {
+ code: OptionClassIdentifier,
+ value: []byte("test"),
+ want: "test",
+ },
+ {
+ code: OptionTFTPServerName,
+ value: []byte("test"),
+ want: "test",
+ },
+ {
+ code: OptionBootfileName,
+ value: []byte("test"),
+ want: "test",
+ },
+ {
+ code: OptionBroadcastAddress,
+ value: []byte{192, 168, 1, 1},
+ want: "192.168.1.1",
+ },
+ {
+ code: OptionRequestedIPAddress,
+ value: []byte{192, 168, 1, 1},
+ want: "192.168.1.1",
+ },
+ {
+ code: OptionIPAddressLeaseTime,
+ value: []byte{0, 0, 0, 12},
+ want: "12s",
+ },
+ {
+ code: OptionDHCPMessageType,
+ value: []byte{1},
+ want: "DISCOVER",
+ },
+ {
+ code: OptionParameterRequestList,
+ value: []byte{3, 4, 5},
+ want: "Router, Time Server, Name Server",
+ },
+ {
+ code: OptionMaximumDHCPMessageSize,
+ value: []byte{1, 2},
+ want: "258",
+ },
+ {
+ code: OptionUserClassInformation,
+ value: []byte{4, 't', 'e', 's', 't', 3, 'f', 'o', 'o'},
+ want: "test, foo",
+ },
+ {
+ code: OptionRelayAgentInformation,
+ value: []byte{1, 4, 129, 168, 0, 1},
+ want: " unknown (1): [129 168 0 1]\n",
+ },
+ {
+ code: OptionClientSystemArchitectureType,
+ value: []byte{0, 0},
+ want: "Intel x86PC",
+ },
+ } {
+ s := parseOption(tt.code, tt.value)
+ if got := s.String(); got != tt.want {
+ t.Errorf("parseOption(%s, %v) = %s, want %s", tt.code, tt.value, got, tt.want)
+ }
+ }
+}
- // Option user class information
- option = []byte{4, 't', 'e', 's', 't'}
- opt, err = ParseOption(OptionUserClassInformation, option)
- require.NoError(t, err)
- require.Equal(t, OptionUserClassInformation, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
+func TestOptionToBytes(t *testing.T) {
+ o := Option{
+ Code: OptionDHCPMessageType,
+ Value: &OptionGeneric{[]byte{byte(MessageTypeDiscover)}},
+ }
+ serialized := o.Value.ToBytes()
+ expected := []byte{1}
+ require.Equal(t, expected, serialized)
+}
- // Option relay agent information
- option = []byte{1, 4, 129, 168, 0, 1}
- opt, err = ParseOption(OptionRelayAgentInformation, option)
- require.NoError(t, err)
- require.Equal(t, OptionRelayAgentInformation, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
+func TestOptionString(t *testing.T) {
+ o := Option{
+ Code: OptionDHCPMessageType,
+ Value: MessageTypeDiscover,
+ }
+ require.Equal(t, "DHCP Message Type: DISCOVER", o.String())
+}
- // Option client system architecture type option
- option = []byte{'t', 'e', 's', 't'}
- opt, err = ParseOption(OptionClientSystemArchitectureType, option)
- require.NoError(t, err)
- require.Equal(t, OptionClientSystemArchitectureType, opt.Code(), "Code")
- require.Equal(t, option, opt.ToBytes(), "ToBytes")
+func TestOptionStringUnknown(t *testing.T) {
+ o := Option{
+ Code: GenericOptionCode(102), // Returend option code.
+ Value: &OptionGeneric{[]byte{byte(MessageTypeDiscover)}},
+ }
+ require.Equal(t, "unknown (102): [1]", o.String())
}
func TestOptionsMarshal(t *testing.T) {
@@ -172,10 +166,7 @@ func TestOptionsMarshal(t *testing.T) {
},
{
opts: Options{
- &OptionGeneric{
- OptionCode: optionCode(5),
- Data: []byte{1, 2, 3, 4},
- },
+ 5: []byte{1, 2, 3, 4},
},
want: []byte{
5 /* key */, 4 /* length */, 1, 2, 3, 4,
@@ -184,14 +175,9 @@ func TestOptionsMarshal(t *testing.T) {
{
// Test sorted key order.
opts: Options{
- &OptionGeneric{
- OptionCode: optionCode(5),
- Data: []byte{1, 2, 3},
- },
- &OptionGeneric{
- OptionCode: optionCode(100),
- Data: []byte{101, 102, 103},
- },
+ 5: []byte{1, 2, 3},
+ 100: []byte{101, 102, 103},
+ 255: []byte{},
},
want: []byte{
5, 3, 1, 2, 3,
@@ -201,10 +187,7 @@ func TestOptionsMarshal(t *testing.T) {
{
// Test RFC 3396.
opts: Options{
- &OptionGeneric{
- OptionCode: optionCode(5),
- Data: bytes.Repeat([]byte{10}, math.MaxUint8+1),
- },
+ 5: bytes.Repeat([]byte{10}, math.MaxUint8+1),
},
want: append(append(
[]byte{5, math.MaxUint8}, bytes.Repeat([]byte{10}, math.MaxUint8)...),
@@ -262,10 +245,7 @@ func TestOptionsUnmarshal(t *testing.T) {
byte(OptionEnd),
},
want: Options{
- &OptionGeneric{
- OptionCode: optionCode(3),
- Data: []byte{5, 6},
- },
+ 3: []byte{5, 6},
},
},
{
@@ -276,10 +256,7 @@ func TestOptionsUnmarshal(t *testing.T) {
byte(OptionEnd),
),
want: Options{
- &OptionGeneric{
- OptionCode: optionCode(3),
- Data: bytes.Repeat([]byte{10}, math.MaxUint8+5),
- },
+ 3: bytes.Repeat([]byte{10}, math.MaxUint8+5),
},
},
{
@@ -289,14 +266,8 @@ func TestOptionsUnmarshal(t *testing.T) {
byte(OptionEnd),
},
want: Options{
- &OptionGeneric{
- OptionCode: optionCode(10),
- Data: []byte{255, 254},
- },
- &OptionGeneric{
- OptionCode: optionCode(11),
- Data: []byte{5, 5, 5},
- },
+ 10: []byte{255, 254},
+ 11: []byte{5, 5, 5},
},
},
{
@@ -305,15 +276,13 @@ func TestOptionsUnmarshal(t *testing.T) {
byte(OptionEnd),
),
want: Options{
- &OptionGeneric{
- OptionCode: optionCode(10),
- Data: []byte{255, 254},
- },
+ 10: []byte{255, 254},
},
},
} {
t.Run(fmt.Sprintf("Test %02d", i), func(t *testing.T) {
- opt, err := OptionsFromBytesWithParser(tt.input, codeGetter, ParseOptionGeneric, true)
+ opt := make(Options)
+ err := opt.fromBytesCheckEnd(tt.input, true)
if tt.wantError {
require.Error(t, err)
} else {