diff options
-rw-r--r-- | dhcpv6/dhcpv6message.go | 15 | ||||
-rw-r--r-- | dhcpv6/modifiers.go | 7 | ||||
-rw-r--r-- | dhcpv6/option_informationrefreshtime.go | 48 | ||||
-rw-r--r-- | dhcpv6/option_informationrefreshtime_test.go | 33 | ||||
-rw-r--r-- | dhcpv6/options.go | 2 |
5 files changed, 105 insertions, 0 deletions
diff --git a/dhcpv6/dhcpv6message.go b/dhcpv6/dhcpv6message.go index f3ed4ef..0dd219d 100644 --- a/dhcpv6/dhcpv6message.go +++ b/dhcpv6/dhcpv6message.go @@ -248,6 +248,21 @@ func (mo MessageOptions) ElapsedTime() time.Duration { return 0 } +// InformationRefreshTime returns the Information Refresh Time option +// as defined by RFC 815 Section 21.23. +// +// InformationRefreshTime returns the provided default if no option is present. +func (mo MessageOptions) InformationRefreshTime(def time.Duration) time.Duration { + opt := mo.Options.GetOne(OptionInformationRefreshTime) + if opt == nil { + return def + } + if t, ok := opt.(*optInformationRefreshTime); ok { + return t.InformationRefreshtime + } + return def +} + // FQDN returns the FQDN option as defined by RFC 4704. func (mo MessageOptions) FQDN() *OptFQDN { opt := mo.Options.GetOne(OptionFQDN) diff --git a/dhcpv6/modifiers.go b/dhcpv6/modifiers.go index fbbad23..8c708d9 100644 --- a/dhcpv6/modifiers.go +++ b/dhcpv6/modifiers.go @@ -2,6 +2,7 @@ package dhcpv6 import ( "net" + "time" "github.com/insomniacslk/dhcp/iana" "github.com/insomniacslk/dhcp/rfc1035label" @@ -175,3 +176,9 @@ func WithIAPD(iaid [4]byte, prefixes ...*OptIAPrefix) Modifier { func WithClientLinkLayerAddress(ht iana.HWType, lla net.HardwareAddr) Modifier { return WithOption(OptClientLinkLayerAddress(ht, lla)) } + +// WithInformationRefreshTime adds an optInformationRefreshTime to the DHCPv6 packet +// using the provided duration +func WithInformationRefreshTime(irt time.Duration) Modifier { + return WithOption(OptInformationRefreshTime(irt)) +} diff --git a/dhcpv6/option_informationrefreshtime.go b/dhcpv6/option_informationrefreshtime.go new file mode 100644 index 0000000..942d5c7 --- /dev/null +++ b/dhcpv6/option_informationrefreshtime.go @@ -0,0 +1,48 @@ +package dhcpv6 + +import ( + "fmt" + "time" + + "github.com/u-root/u-root/pkg/uio" +) + +// OptInformationRefreshTime implements OptionInformationRefreshTime option. +// https://tools.ietf.org/html/rfc8415#section-21.23 +func OptInformationRefreshTime(irt time.Duration) *optInformationRefreshTime { + return &optInformationRefreshTime{irt} +} + +// optInformationRefreshTime represents an OptionInformationRefreshTime. +type optInformationRefreshTime struct { + InformationRefreshtime time.Duration +} + +// Code returns the option's code +func (op *optInformationRefreshTime) Code() OptionCode { + return OptionInformationRefreshTime +} + +// ToBytes serializes the option and returns it as a sequence of bytes +func (op *optInformationRefreshTime) ToBytes() []byte { + buf := uio.NewBigEndianBuffer(nil) + irt := Duration{op.InformationRefreshtime} + irt.Marshal(buf) + return buf.Data() +} + +func (op *optInformationRefreshTime) String() string { + return fmt.Sprintf("InformationRefreshTime: %v", op.InformationRefreshtime) +} + +// parseOptInformationRefreshTime builds an optInformationRefreshTime structure from a sequence +// of bytes. The input data does not include option code and length bytes. +func parseOptInformationRefreshTime(data []byte) (*optInformationRefreshTime, error) { + var opt optInformationRefreshTime + buf := uio.NewBigEndianBuffer(data) + + var irt Duration + irt.Unmarshal(buf) + opt.InformationRefreshtime = irt.Duration + return &opt, buf.FinError() +} diff --git a/dhcpv6/option_informationrefreshtime_test.go b/dhcpv6/option_informationrefreshtime_test.go new file mode 100644 index 0000000..68f0855 --- /dev/null +++ b/dhcpv6/option_informationrefreshtime_test.go @@ -0,0 +1,33 @@ +package dhcpv6 + +import ( + "bytes" + "testing" + "time" +) + +func TestOptInformationRefreshTime(t *testing.T) { + opt, err := parseOptInformationRefreshTime([]byte{0xaa, 0xbb, 0xcc, 0xdd}) + if err != nil { + t.Fatal(err) + } + if informationRefreshTime := opt.InformationRefreshtime; informationRefreshTime != time.Duration(0xaabbccdd) * time.Second { + t.Fatalf("Invalid information refresh time. Expected 0xaabb, got %v", informationRefreshTime) + } +} + +func TestOptInformationRefreshTimeToBytes(t *testing.T) { + opt := OptInformationRefreshTime(0) + expected := []byte{0, 0, 0, 0} + if toBytes := opt.ToBytes(); !bytes.Equal(expected, toBytes) { + t.Fatalf("Invalid ToBytes output. Expected %v, got %v", expected, toBytes) + } +} + +func TestOptInformationRefreshTimeString(t *testing.T) { + opt := OptInformationRefreshTime(3600 * time.Second) + expected := "InformationRefreshTime: 1h0m0s" + if optString := opt.String(); optString != expected { + t.Fatalf("Invalid elapsed time string. Expected %v, got %v", expected, optString) + } +} diff --git a/dhcpv6/options.go b/dhcpv6/options.go index 16bc8d7..0ff5148 100644 --- a/dhcpv6/options.go +++ b/dhcpv6/options.go @@ -75,6 +75,8 @@ func ParseOption(code OptionCode, optData []byte) (Option, error) { opt, err = ParseOptIAPD(optData) case OptionIAPrefix: opt, err = ParseOptIAPrefix(optData) + case OptionInformationRefreshTime: + opt, err = parseOptInformationRefreshTime(optData) case OptionRemoteID: opt, err = ParseOptRemoteID(optData) case OptionFQDN: |