diff options
Diffstat (limited to 'dhcpv6')
-rw-r--r-- | dhcpv6/dhcpv6message.go | 18 | ||||
-rw-r--r-- | dhcpv6/dhcpv6relay_test.go | 4 | ||||
-rw-r--r-- | dhcpv6/option_elapsedtime.go | 33 | ||||
-rw-r--r-- | dhcpv6/option_elapsedtime_test.go | 24 | ||||
-rw-r--r-- | dhcpv6/option_iaaddress_test.go | 6 | ||||
-rw-r--r-- | dhcpv6/option_iaprefix_test.go | 4 | ||||
-rw-r--r-- | dhcpv6/option_nontemporaryaddress_test.go | 12 | ||||
-rw-r--r-- | dhcpv6/option_relaymsg_test.go | 13 | ||||
-rw-r--r-- | dhcpv6/options.go | 2 |
9 files changed, 57 insertions, 59 deletions
diff --git a/dhcpv6/dhcpv6message.go b/dhcpv6/dhcpv6message.go index d099386..4e5717f 100644 --- a/dhcpv6/dhcpv6message.go +++ b/dhcpv6/dhcpv6message.go @@ -116,6 +116,20 @@ func (mo MessageOptions) BootFileURL() string { return "" } +// ElapsedTime returns the Elapsed Time option as defined by RFC 3315 Section 22.9. +// +// ElapsedTime returns a duration of 0 if the option is not present. +func (mo MessageOptions) ElapsedTime() time.Duration { + opt := mo.Options.GetOne(OptionElapsedTime) + if opt == nil { + return 0 + } + if t, ok := opt.(*optElapsedTime); ok { + return t.ElapsedTime + } + return 0 +} + // Message represents a DHCPv6 Message as defined by RFC 3315 Section 6. type Message struct { MessageType MessageType @@ -164,7 +178,7 @@ func NewSolicit(hwaddr net.HardwareAddr, modifiers ...Modifier) (*Message, error OptionDNSRecursiveNameServer, OptionDomainSearchList, )) - m.AddOption(&OptElapsedTime{}) + m.AddOption(OptElapsedTime(0)) if len(hwaddr) < 4 { return nil, errors.New("short hardware addrss: less than 4 bytes") } @@ -233,7 +247,7 @@ func NewRequestFromAdvertise(adv *Message, modifiers ...Modifier) (*Message, err } req.AddOption(sid) // add Elapsed Time - req.AddOption(&OptElapsedTime{}) + req.AddOption(OptElapsedTime(0)) // add IA_NA iana := adv.Options.OneIANA() if iana == nil { diff --git a/dhcpv6/dhcpv6relay_test.go b/dhcpv6/dhcpv6relay_test.go index 773c047..a7918ab 100644 --- a/dhcpv6/dhcpv6relay_test.go +++ b/dhcpv6/dhcpv6relay_test.go @@ -65,9 +65,7 @@ func TestRelayMessageToBytes(t *testing.T) { TransactionID: TransactionID{0xaa, 0xbb, 0xcc}, Options: MessageOptions{ Options: []Option{ - &OptElapsedTime{ - ElapsedTime: 0, - }, + OptElapsedTime(0), }, }, }, diff --git a/dhcpv6/option_elapsedtime.go b/dhcpv6/option_elapsedtime.go index 194122e..0e2547f 100644 --- a/dhcpv6/option_elapsedtime.go +++ b/dhcpv6/option_elapsedtime.go @@ -2,38 +2,41 @@ package dhcpv6 import ( "fmt" + "time" "github.com/u-root/u-root/pkg/uio" ) -// OptElapsedTime implements the Elapsed Time option. -// -// This module defines the OptElapsedTime structure. -// https://www.ietf.org/rfc/rfc3315.txt -type OptElapsedTime struct { - ElapsedTime uint16 +// OptElapsedTime returns an Elapsed Time option as defined by RFC 3315 Section +// 22.9. +func OptElapsedTime(dur time.Duration) Option { + return &optElapsedTime{ElapsedTime: dur} } -func (op *OptElapsedTime) Code() OptionCode { +type optElapsedTime struct { + ElapsedTime time.Duration +} + +func (*optElapsedTime) Code() OptionCode { return OptionElapsedTime } // ToBytes marshals this option to bytes. -func (op *OptElapsedTime) ToBytes() []byte { +func (op *optElapsedTime) ToBytes() []byte { buf := uio.NewBigEndianBuffer(nil) - buf.Write16(op.ElapsedTime) + buf.Write16(uint16(op.ElapsedTime.Round(10*time.Millisecond) / (10 * time.Millisecond))) return buf.Data() } -func (op *OptElapsedTime) String() string { - return fmt.Sprintf("OptElapsedTime{elapsedtime=%v}", op.ElapsedTime) +func (op *optElapsedTime) String() string { + return fmt.Sprintf("ElapsedTime: %s", op.ElapsedTime) } -// build an OptElapsedTime structure from a sequence of bytes. +// build 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 parseOptElapsedTime(data []byte) (*optElapsedTime, error) { + var opt optElapsedTime buf := uio.NewBigEndianBuffer(data) - opt.ElapsedTime = buf.Read16() + opt.ElapsedTime = time.Duration(buf.Read16()) * 10 * time.Millisecond return &opt, buf.FinError() } diff --git a/dhcpv6/option_elapsedtime_test.go b/dhcpv6/option_elapsedtime_test.go index 3442281..91fab45 100644 --- a/dhcpv6/option_elapsedtime_test.go +++ b/dhcpv6/option_elapsedtime_test.go @@ -3,49 +3,41 @@ package dhcpv6 import ( "bytes" "testing" + "time" "github.com/stretchr/testify/require" ) func TestOptElapsedTime(t *testing.T) { - opt, err := ParseOptElapsedTime([]byte{0xaa, 0xbb}) + opt, err := parseOptElapsedTime([]byte{0xaa, 0xbb}) if err != nil { t.Fatal(err) } - if elapsedTime := opt.ElapsedTime; elapsedTime != 0xaabb { + if elapsedTime := opt.ElapsedTime; elapsedTime != 0xaabb*10*time.Millisecond { t.Fatalf("Invalid elapsed time. Expected 0xaabb, got %v", elapsedTime) } } func TestOptElapsedTimeToBytes(t *testing.T) { - opt := OptElapsedTime{} + opt := OptElapsedTime(0) expected := []byte{0, 0} if toBytes := opt.ToBytes(); !bytes.Equal(expected, toBytes) { t.Fatalf("Invalid ToBytes output. Expected %v, got %v", expected, toBytes) } } -func TestOptElapsedTimeSetGetElapsedTime(t *testing.T) { - opt := OptElapsedTime{} - opt.ElapsedTime = 10 - if elapsedTime := opt.ElapsedTime; elapsedTime != 10 { - t.Fatalf("Invalid elapsed time. Expected 10, got %v", elapsedTime) - } -} - func TestOptElapsedTimeString(t *testing.T) { - opt := OptElapsedTime{} - opt.ElapsedTime = 10 - expected := "OptElapsedTime{elapsedtime=10}" + opt := OptElapsedTime(100 * time.Millisecond) + expected := "ElapsedTime: 100ms" if optString := opt.String(); optString != expected { t.Fatalf("Invalid elapsed time string. Expected %v, got %v", expected, optString) } } func TestOptElapsedTimeParseInvalidOption(t *testing.T) { - _, err := ParseOptElapsedTime([]byte{0xaa}) + _, err := parseOptElapsedTime([]byte{0xaa}) require.Error(t, err, "A short option should return an error") - _, err = ParseOptElapsedTime([]byte{0xaa, 0xbb, 0xcc}) + _, 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 1b80b7d..4db999c 100644 --- a/dhcpv6/option_iaaddress_test.go +++ b/dhcpv6/option_iaaddress_test.go @@ -48,16 +48,14 @@ func TestOptIAAddressToBytes(t *testing.T) { expected := append(ipBytes, []byte{ 0xa, 0xb, 0xc, 0xd, // preferred lifetime 0xe, 0xf, 0x1, 0x2, // valid lifetime - 0, 8, 0, 2, 0xaa, 0xbb, // options + 0, 8, 0, 2, 0x00, 0x01, // options }...) opt := OptIAAddress{ IPv6Addr: net.IP(ipBytes), PreferredLifetime: 0x0a0b0c0d * time.Second, ValidLifetime: 0x0e0f0102 * time.Second, Options: []Option{ - &OptElapsedTime{ - ElapsedTime: 0xaabb, - }, + OptElapsedTime(10 * time.Millisecond), }, } require.Equal(t, expected, opt.ToBytes()) diff --git a/dhcpv6/option_iaprefix_test.go b/dhcpv6/option_iaprefix_test.go index a1c140e..baa4808 100644 --- a/dhcpv6/option_iaprefix_test.go +++ b/dhcpv6/option_iaprefix_test.go @@ -41,7 +41,7 @@ func TestOptIAPrefixToBytes(t *testing.T) { 0xee, 0xff, 0x00, 0x11, // validLifetime 36, // prefixLength 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ipv6Prefix - 0, 8, 0, 2, 0xaa, 0xbb, // options + 0, 8, 0, 2, 0x00, 0x01, // options } opt := OptIAPrefix{ PreferredLifetime: 0xaabbccdd * time.Second, @@ -49,7 +49,7 @@ func TestOptIAPrefixToBytes(t *testing.T) { prefixLength: 36, ipv6Prefix: net.IPv6zero, } - opt.Options = append(opt.Options, &OptElapsedTime{ElapsedTime: 0xaabb}) + opt.Options.Add(OptElapsedTime(10 * time.Millisecond)) toBytes := opt.ToBytes() if !bytes.Equal(toBytes, buf) { t.Fatalf("Invalid ToBytes result. Expected %v, got %v", buf, toBytes) diff --git a/dhcpv6/option_nontemporaryaddress_test.go b/dhcpv6/option_nontemporaryaddress_test.go index 6ad5f97..ceee9ec 100644 --- a/dhcpv6/option_nontemporaryaddress_test.go +++ b/dhcpv6/option_nontemporaryaddress_test.go @@ -46,14 +46,14 @@ func TestOptIANAGetOneOption(t *testing.T) { IPv6Addr: net.ParseIP("::1"), } opt := OptIANA{ - Options: []Option{&OptElapsedTime{}, oaddr}, + Options: []Option{OptElapsedTime(0), oaddr}, } require.Equal(t, oaddr, opt.GetOneOption(OptionIAAddr)) } func TestOptIANAAddOption(t *testing.T) { opt := OptIANA{} - opt.AddOption(&OptElapsedTime{}) + opt.AddOption(OptElapsedTime(0)) require.Equal(t, 1, len(opt.Options)) require.Equal(t, OptionElapsedTime, opt.Options[0].Code()) } @@ -63,7 +63,7 @@ func TestOptIANAGetOneOptionMissingOpt(t *testing.T) { IPv6Addr: net.ParseIP("::1"), } opt := OptIANA{ - Options: []Option{&OptElapsedTime{}, oaddr}, + Options: []Option{OptElapsedTime(0), oaddr}, } require.Equal(t, nil, opt.GetOneOption(OptionDNSRecursiveNameServer)) } @@ -93,16 +93,14 @@ func TestOptIANAToBytes(t *testing.T) { T1: 12345 * time.Second, T2: 54321 * time.Second, Options: []Option{ - &OptElapsedTime{ - ElapsedTime: 0xaabb, - }, + OptElapsedTime(10 * time.Millisecond), }, } expected := []byte{ 1, 2, 3, 4, // IA ID 0, 0, 0x30, 0x39, // T1 = 12345 0, 0, 0xd4, 0x31, // T2 = 54321 - 0, 8, 0, 2, 0xaa, 0xbb, + 0, 8, 0, 2, 0x00, 0x01, } require.Equal(t, expected, opt.ToBytes()) } diff --git a/dhcpv6/option_relaymsg_test.go b/dhcpv6/option_relaymsg_test.go index 887bf95..a39439b 100644 --- a/dhcpv6/option_relaymsg_test.go +++ b/dhcpv6/option_relaymsg_test.go @@ -3,6 +3,7 @@ package dhcpv6 import ( "reflect" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -62,7 +63,7 @@ func TestRelayMsgParseOptRelayMsgSingleEncapsulation(t *testing.T) { 0xaa, 0xbb, 0xcc, // transaction ID 0, 8, // option: elapsed time 0, 2, // option length - 0x11, 0x22, // option value + 0x00, 0x01, // option value }) if err != nil { t.Fatal(err) @@ -109,14 +110,8 @@ func TestRelayMsgParseOptRelayMsgSingleEncapsulation(t *testing.T) { if len(innerDHCP.Options.Options) != 1 { t.Fatalf("Invalid inner DHCP options length. Expected 1, got %v", len(innerDHCP.Options.Options)) } - innerOpt := innerDHCP.Options.Options[0] - eto, ok := innerOpt.(*OptElapsedTime) - if !ok { - t.Fatalf("Invalid inner option type. Expected OptElapsedTime, got %v", - reflect.TypeOf(innerOpt), - ) - } - if eTime := eto.ElapsedTime; eTime != 0x1122 { + eTime := innerDHCP.Options.ElapsedTime() + if eTime != 10*time.Millisecond { t.Fatalf("Invalid elapsed time. Expected 0x1122, got 0x%04x", eTime) } } diff --git a/dhcpv6/options.go b/dhcpv6/options.go index 9d0ff9d..63261c1 100644 --- a/dhcpv6/options.go +++ b/dhcpv6/options.go @@ -52,7 +52,7 @@ func ParseOption(code OptionCode, optData []byte) (Option, error) { err = o.FromBytes(optData) opt = &o case OptionElapsedTime: - opt, err = ParseOptElapsedTime(optData) + opt, err = parseOptElapsedTime(optData) case OptionRelayMsg: opt, err = ParseOptRelayMsg(optData) case OptionStatusCode: |