summaryrefslogtreecommitdiffhomepage
path: root/dhcpv6
diff options
context:
space:
mode:
Diffstat (limited to 'dhcpv6')
-rw-r--r--dhcpv6/dhcpv6message.go18
-rw-r--r--dhcpv6/dhcpv6relay_test.go4
-rw-r--r--dhcpv6/option_elapsedtime.go33
-rw-r--r--dhcpv6/option_elapsedtime_test.go24
-rw-r--r--dhcpv6/option_iaaddress_test.go6
-rw-r--r--dhcpv6/option_iaprefix_test.go4
-rw-r--r--dhcpv6/option_nontemporaryaddress_test.go12
-rw-r--r--dhcpv6/option_relaymsg_test.go13
-rw-r--r--dhcpv6/options.go2
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: