From 9a95b101e205d121810f3922999e1af1d39e4c43 Mon Sep 17 00:00:00 2001 From: Chris Koch Date: Sat, 28 Dec 2019 06:30:10 -0800 Subject: v6: use time.Duration for duration fields Signed-off-by: Chris Koch --- dhcpv6/option_iaaddress.go | 22 +++++++++++++----- dhcpv6/option_iaaddress_test.go | 17 +++++++------- dhcpv6/option_iaprefix.go | 22 +++++++++++++----- dhcpv6/option_iaprefix_test.go | 17 +++++++------- dhcpv6/option_nontemporaryaddress.go | 38 ++++++++++++++++++++++++++----- dhcpv6/option_nontemporaryaddress_test.go | 7 +++--- dhcpv6/option_prefixdelegation.go | 22 +++++++++++++----- dhcpv6/option_prefixdelegation_test.go | 15 ++++++------ netboot/netconf.go | 10 ++++---- netboot/netconf_test.go | 21 +++++++++-------- 10 files changed, 126 insertions(+), 65 deletions(-) diff --git a/dhcpv6/option_iaaddress.go b/dhcpv6/option_iaaddress.go index 882e627..c4184e1 100644 --- a/dhcpv6/option_iaaddress.go +++ b/dhcpv6/option_iaaddress.go @@ -3,6 +3,7 @@ package dhcpv6 import ( "fmt" "net" + "time" "github.com/u-root/u-root/pkg/uio" ) @@ -13,8 +14,8 @@ import ( // https://www.ietf.org/rfc/rfc3633.txt type OptIAAddress struct { IPv6Addr net.IP - PreferredLifetime uint32 - ValidLifetime uint32 + PreferredLifetime time.Duration + ValidLifetime time.Duration Options Options } @@ -27,8 +28,12 @@ func (op *OptIAAddress) Code() OptionCode { func (op *OptIAAddress) ToBytes() []byte { buf := uio.NewBigEndianBuffer(nil) buf.WriteBytes(op.IPv6Addr.To16()) - buf.Write32(op.PreferredLifetime) - buf.Write32(op.ValidLifetime) + + t1 := Duration{op.PreferredLifetime} + t1.Marshal(buf) + t2 := Duration{op.ValidLifetime} + t2.Marshal(buf) + buf.WriteBytes(op.Options.ToBytes()) return buf.Data() } @@ -45,8 +50,13 @@ func ParseOptIAAddress(data []byte) (*OptIAAddress, error) { var opt OptIAAddress buf := uio.NewBigEndianBuffer(data) opt.IPv6Addr = net.IP(buf.CopyN(net.IPv6len)) - opt.PreferredLifetime = buf.Read32() - opt.ValidLifetime = buf.Read32() + + var t1, t2 Duration + t1.Unmarshal(buf) + t2.Unmarshal(buf) + opt.PreferredLifetime = t1.Duration + opt.ValidLifetime = t2.Duration + if err := opt.Options.FromBytes(buf.ReadAll()); err != nil { return nil, err } diff --git a/dhcpv6/option_iaaddress_test.go b/dhcpv6/option_iaaddress_test.go index 511a907..1b80b7d 100644 --- a/dhcpv6/option_iaaddress_test.go +++ b/dhcpv6/option_iaaddress_test.go @@ -3,6 +3,7 @@ package dhcpv6 import ( "net" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -17,8 +18,8 @@ func TestOptIAAddressParse(t *testing.T) { opt, err := ParseOptIAAddress(data) require.NoError(t, err) require.Equal(t, net.IP(ipaddr), opt.IPv6Addr) - require.Equal(t, uint32(0x0a0b0c0d), opt.PreferredLifetime) - require.Equal(t, uint32(0x0e0f0102), opt.ValidLifetime) + require.Equal(t, 0x0a0b0c0d*time.Second, opt.PreferredLifetime) + require.Equal(t, 0x0e0f0102*time.Second, opt.ValidLifetime) } func TestOptIAAddressParseInvalidTooShort(t *testing.T) { @@ -51,8 +52,8 @@ func TestOptIAAddressToBytes(t *testing.T) { }...) opt := OptIAAddress{ IPv6Addr: net.IP(ipBytes), - PreferredLifetime: 0x0a0b0c0d, - ValidLifetime: 0x0e0f0102, + PreferredLifetime: 0x0a0b0c0d * time.Second, + ValidLifetime: 0x0e0f0102 * time.Second, Options: []Option{ &OptElapsedTime{ ElapsedTime: 0xaabb, @@ -65,8 +66,8 @@ func TestOptIAAddressToBytes(t *testing.T) { func TestOptIAAddressString(t *testing.T) { ipaddr := []byte{0x24, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} data := append(ipaddr, []byte{ - 0xa, 0xb, 0xc, 0xd, // preferred lifetime - 0xe, 0xf, 0x1, 0x2, // valid lifetime + 0x00, 0x00, 0x00, 70, // preferred lifetime + 0x00, 0x00, 0x00, 50, // valid lifetime 0, 8, 0, 2, 0xaa, 0xbb, // options }...) opt, err := ParseOptIAAddress(data) @@ -80,12 +81,12 @@ func TestOptIAAddressString(t *testing.T) { ) require.Contains( t, str, - "preferredlifetime=168496141", + "preferredlifetime=1m10s", "String() should return the preferredlifetime", ) require.Contains( t, str, - "validlifetime=235864322", + "validlifetime=50s", "String() should return the validlifetime", ) } diff --git a/dhcpv6/option_iaprefix.go b/dhcpv6/option_iaprefix.go index 7260d2c..abd7a34 100644 --- a/dhcpv6/option_iaprefix.go +++ b/dhcpv6/option_iaprefix.go @@ -3,6 +3,7 @@ package dhcpv6 import ( "fmt" "net" + "time" "github.com/u-root/u-root/pkg/uio" ) @@ -12,8 +13,8 @@ import ( // This module defines the OptIAPrefix structure. // https://www.ietf.org/rfc/rfc3633.txt type OptIAPrefix struct { - PreferredLifetime uint32 - ValidLifetime uint32 + PreferredLifetime time.Duration + ValidLifetime time.Duration prefixLength byte ipv6Prefix net.IP Options Options @@ -26,8 +27,12 @@ func (op *OptIAPrefix) Code() OptionCode { // ToBytes marshals this option according to RFC 3633, Section 10. func (op *OptIAPrefix) ToBytes() []byte { buf := uio.NewBigEndianBuffer(nil) - buf.Write32(op.PreferredLifetime) - buf.Write32(op.ValidLifetime) + + t1 := Duration{op.PreferredLifetime} + t1.Marshal(buf) + t2 := Duration{op.ValidLifetime} + t2.Marshal(buf) + buf.Write8(op.prefixLength) buf.WriteBytes(op.ipv6Prefix.To16()) buf.WriteBytes(op.Options.ToBytes()) @@ -73,8 +78,13 @@ func (op *OptIAPrefix) DelOption(code OptionCode) { func ParseOptIAPrefix(data []byte) (*OptIAPrefix, error) { buf := uio.NewBigEndianBuffer(data) var opt OptIAPrefix - opt.PreferredLifetime = buf.Read32() - opt.ValidLifetime = buf.Read32() + + var t1, t2 Duration + t1.Unmarshal(buf) + t2.Unmarshal(buf) + opt.PreferredLifetime = t1.Duration + opt.ValidLifetime = t2.Duration + opt.prefixLength = buf.Read8() opt.ipv6Prefix = net.IP(buf.CopyN(net.IPv6len)) if err := opt.Options.FromBytes(buf.ReadAll()); err != nil { diff --git a/dhcpv6/option_iaprefix_test.go b/dhcpv6/option_iaprefix_test.go index 6a98b8b..7a24d2b 100644 --- a/dhcpv6/option_iaprefix_test.go +++ b/dhcpv6/option_iaprefix_test.go @@ -4,6 +4,7 @@ import ( "bytes" "net" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -20,10 +21,10 @@ func TestOptIAPrefix(t *testing.T) { if err != nil { t.Fatal(err) } - if pl := opt.PreferredLifetime; pl != 0xaabbccdd { + if pl := opt.PreferredLifetime; pl != 0xaabbccdd*time.Second { t.Fatalf("Invalid Preferred Lifetime. Expected 0xaabbccdd, got %v", pl) } - if vl := opt.ValidLifetime; vl != 0xeeff0011 { + if vl := opt.ValidLifetime; vl != 0xeeff0011*time.Second { t.Fatalf("Invalid Valid Lifetime. Expected 0xeeff0011, got %v", vl) } if pr := opt.PrefixLength(); pr != 36 { @@ -43,8 +44,8 @@ func TestOptIAPrefixToBytes(t *testing.T) { 0, 8, 0, 2, 0xaa, 0xbb, // options } opt := OptIAPrefix{ - PreferredLifetime: 0xaabbccdd, - ValidLifetime: 0xeeff0011, + PreferredLifetime: 0xaabbccdd * time.Second, + ValidLifetime: 0xeeff0011 * time.Second, prefixLength: 36, ipv6Prefix: net.IPv6zero, } @@ -69,8 +70,8 @@ func TestOptIAPrefixParseInvalidTooShort(t *testing.T) { func TestOptIAPrefixString(t *testing.T) { buf := []byte{ - 0xaa, 0xbb, 0xcc, 0xdd, // preferredLifetime - 0xee, 0xff, 0x00, 0x11, // validLifetime + 0x00, 0x00, 0x00, 60, // preferredLifetime + 0x00, 0x00, 0x00, 50, // validLifetime 36, // prefixLength 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ipv6Prefix } @@ -85,12 +86,12 @@ func TestOptIAPrefixString(t *testing.T) { ) require.Contains( t, str, - "preferredlifetime=2864434397", + "preferredlifetime=1m", "String() should return the preferredlifetime", ) require.Contains( t, str, - "validlifetime=4009689105", + "validlifetime=50s", "String() should return the validlifetime", ) } diff --git a/dhcpv6/option_nontemporaryaddress.go b/dhcpv6/option_nontemporaryaddress.go index 031f22c..6b3d8d6 100644 --- a/dhcpv6/option_nontemporaryaddress.go +++ b/dhcpv6/option_nontemporaryaddress.go @@ -2,10 +2,29 @@ package dhcpv6 import ( "fmt" + "time" "github.com/u-root/u-root/pkg/uio" ) +// Duration is a duration as embedded in IA messages (IAPD, IANA, IATA). +type Duration struct { + time.Duration +} + +// Marshal encodes the time in uint32 seconds as defined by RFC 3315 for IANA +// messages. +func (d Duration) Marshal(buf *uio.Lexer) { + buf.Write32(uint32(d.Duration.Round(time.Second) / time.Second)) +} + +// Unmarshal decodes time from uint32 seconds as defined by RFC 3315 for IANA +// messages. +func (d *Duration) Unmarshal(buf *uio.Lexer) { + t := buf.Read32() + d.Duration = time.Duration(t) * time.Second +} + // OptIANA implements the identity association for non-temporary addresses // option. // @@ -13,8 +32,8 @@ import ( // https://www.ietf.org/rfc/rfc3633.txt type OptIANA struct { IaId [4]byte - T1 uint32 - T2 uint32 + T1 time.Duration + T2 time.Duration Options Options } @@ -26,8 +45,10 @@ func (op *OptIANA) Code() OptionCode { func (op *OptIANA) ToBytes() []byte { buf := uio.NewBigEndianBuffer(nil) buf.WriteBytes(op.IaId[:]) - buf.Write32(op.T1) - buf.Write32(op.T2) + t1 := Duration{op.T1} + t1.Marshal(buf) + t2 := Duration{op.T2} + t2.Marshal(buf) buf.WriteBytes(op.Options.ToBytes()) return buf.Data() } @@ -59,8 +80,13 @@ func ParseOptIANA(data []byte) (*OptIANA, error) { var opt OptIANA buf := uio.NewBigEndianBuffer(data) buf.ReadBytes(opt.IaId[:]) - opt.T1 = buf.Read32() - opt.T2 = buf.Read32() + + var t1, t2 Duration + t1.Unmarshal(buf) + t2.Unmarshal(buf) + opt.T1 = t1.Duration + opt.T2 = t2.Duration + if err := opt.Options.FromBytes(buf.ReadAll()); err != nil { return nil, err } diff --git a/dhcpv6/option_nontemporaryaddress_test.go b/dhcpv6/option_nontemporaryaddress_test.go index afe6917..6ad5f97 100644 --- a/dhcpv6/option_nontemporaryaddress_test.go +++ b/dhcpv6/option_nontemporaryaddress_test.go @@ -3,6 +3,7 @@ package dhcpv6 import ( "net" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -89,8 +90,8 @@ func TestOptIANADelOption(t *testing.T) { func TestOptIANAToBytes(t *testing.T) { opt := OptIANA{ IaId: [4]byte{1, 2, 3, 4}, - T1: 12345, - T2: 54321, + T1: 12345 * time.Second, + T2: 54321 * time.Second, Options: []Option{ &OptElapsedTime{ ElapsedTime: 0xaabb, @@ -124,7 +125,7 @@ func TestOptIANAString(t *testing.T) { ) require.Contains( t, str, - "t1=1, t2=2", + "t1=1s, t2=2s", "String() should return the T1/T2 options", ) require.Contains( diff --git a/dhcpv6/option_prefixdelegation.go b/dhcpv6/option_prefixdelegation.go index d366673..fe72936 100644 --- a/dhcpv6/option_prefixdelegation.go +++ b/dhcpv6/option_prefixdelegation.go @@ -2,6 +2,7 @@ package dhcpv6 import ( "fmt" + "time" "github.com/u-root/u-root/pkg/uio" ) @@ -10,8 +11,8 @@ import ( // delegation option defined by RFC 3633, Section 9. type OptIAForPrefixDelegation struct { IaId [4]byte - T1 uint32 - T2 uint32 + T1 time.Duration + T2 time.Duration Options Options } @@ -24,8 +25,12 @@ func (op *OptIAForPrefixDelegation) Code() OptionCode { func (op *OptIAForPrefixDelegation) ToBytes() []byte { buf := uio.NewBigEndianBuffer(nil) buf.WriteBytes(op.IaId[:]) - buf.Write32(op.T1) - buf.Write32(op.T2) + + t1 := Duration{op.T1} + t1.Marshal(buf) + t2 := Duration{op.T2} + t2.Marshal(buf) + buf.WriteBytes(op.Options.ToBytes()) return buf.Data() } @@ -53,8 +58,13 @@ func ParseOptIAForPrefixDelegation(data []byte) (*OptIAForPrefixDelegation, erro var opt OptIAForPrefixDelegation buf := uio.NewBigEndianBuffer(data) buf.ReadBytes(opt.IaId[:]) - opt.T1 = buf.Read32() - opt.T2 = buf.Read32() + + var t1, t2 Duration + t1.Unmarshal(buf) + t2.Unmarshal(buf) + opt.T1 = t1.Duration + opt.T2 = t2.Duration + if err := opt.Options.FromBytes(buf.ReadAll()); err != nil { return nil, err } diff --git a/dhcpv6/option_prefixdelegation_test.go b/dhcpv6/option_prefixdelegation_test.go index 802a3a6..1fff283 100644 --- a/dhcpv6/option_prefixdelegation_test.go +++ b/dhcpv6/option_prefixdelegation_test.go @@ -3,6 +3,7 @@ package dhcpv6 import ( "net" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -22,8 +23,8 @@ func TestOptIAForPrefixDelegationParseOptIAForPrefixDelegation(t *testing.T) { require.NoError(t, err) require.Equal(t, OptionIAPD, opt.Code()) require.Equal(t, [4]byte{1, 0, 0, 0}, opt.IaId) - require.Equal(t, uint32(1), opt.T1) - require.Equal(t, uint32(2), opt.T2) + require.Equal(t, time.Second, opt.T1) + require.Equal(t, 2*time.Second, opt.T2) } func TestOptIAForPrefixDelegationParseOptIAForPrefixDelegationInvalidLength(t *testing.T) { @@ -106,15 +107,15 @@ func TestOptIAForPrefixDelegationDelOption(t *testing.T) { func TestOptIAForPrefixDelegationToBytes(t *testing.T) { oaddr := OptIAPrefix{} - oaddr.PreferredLifetime = 0xaabbccdd - oaddr.ValidLifetime = 0xeeff0011 + oaddr.PreferredLifetime = 0xaabbccdd * time.Second + oaddr.ValidLifetime = 0xeeff0011 * time.Second oaddr.SetPrefixLength(36) oaddr.SetIPv6Prefix(net.IPv6loopback) opt := OptIAForPrefixDelegation{} opt.IaId = [4]byte{1, 2, 3, 4} - opt.T1 = 12345 - opt.T2 = 54321 + opt.T1 = 12345 * time.Second + opt.T2 = 54321 * time.Second opt.Options = append(opt.Options, &oaddr) expected := []byte{ @@ -152,7 +153,7 @@ func TestOptIAForPrefixDelegationString(t *testing.T) { ) require.Contains( t, str, - "t1=1, t2=2", + "t1=1s, t2=2s", "String() should return the T1/T2 options", ) require.Contains( diff --git a/netboot/netconf.go b/netboot/netconf.go index 2ce658b..96bfff2 100644 --- a/netboot/netconf.go +++ b/netboot/netconf.go @@ -20,8 +20,8 @@ import ( // AddrConf holds a single IP address configuration for a NIC type AddrConf struct { IPNet net.IPNet - PreferredLifetime int - ValidLifetime int + PreferredLifetime time.Duration + ValidLifetime time.Duration } // NetConf holds multiple IP configuration for a NIC, and DNS configuration @@ -55,8 +55,8 @@ func GetNetConfFromPacketv6(d *dhcpv6.Message) (*NetConf, error) { IP: iaaddr.IPv6Addr, Mask: netmask, }, - PreferredLifetime: int(iaaddr.PreferredLifetime), - ValidLifetime: int(iaaddr.ValidLifetime), + PreferredLifetime: iaaddr.PreferredLifetime, + ValidLifetime: iaaddr.ValidLifetime, }) } // get DNS configuration @@ -110,7 +110,7 @@ func GetNetConfFromPacketv4(d *dhcpv4.DHCPv4) (*NetConf, error) { Mask: netmask, }, PreferredLifetime: 0, - ValidLifetime: int(leaseTime / time.Second), + ValidLifetime: leaseTime, }) // get DNS configuration diff --git a/netboot/netconf_test.go b/netboot/netconf_test.go index 1341af4..8b1f5f7 100644 --- a/netboot/netconf_test.go +++ b/netboot/netconf_test.go @@ -4,6 +4,7 @@ import ( "log" "net" "testing" + "time" "github.com/insomniacslk/dhcp/dhcpv4" "github.com/insomniacslk/dhcp/dhcpv6" @@ -43,8 +44,8 @@ func TestGetNetConfFromPacketv6NoDNS(t *testing.T) { addrs := []dhcpv6.OptIAAddress{ dhcpv6.OptIAAddress{ IPv6Addr: net.ParseIP("::1"), - PreferredLifetime: 3600, - ValidLifetime: 5200, + PreferredLifetime: 3600 * time.Second, + ValidLifetime: 5200 * time.Second, }, } adv := getAdv(dhcpv6.WithIANA(addrs...)) @@ -56,8 +57,8 @@ func TestGetNetConfFromPacketv6NoSearchList(t *testing.T) { addrs := []dhcpv6.OptIAAddress{ dhcpv6.OptIAAddress{ IPv6Addr: net.ParseIP("::1"), - PreferredLifetime: 3600, - ValidLifetime: 5200, + PreferredLifetime: 3600 * time.Second, + ValidLifetime: 5200 * time.Second, }, } adv := getAdv( @@ -72,8 +73,8 @@ func TestGetNetConfFromPacketv6(t *testing.T) { addrs := []dhcpv6.OptIAAddress{ dhcpv6.OptIAAddress{ IPv6Addr: net.ParseIP("::1"), - PreferredLifetime: 3600, - ValidLifetime: 5200, + PreferredLifetime: 3600 * time.Second, + ValidLifetime: 5200 * time.Second, }, } adv := getAdv( @@ -86,8 +87,8 @@ func TestGetNetConfFromPacketv6(t *testing.T) { // check addresses require.Equal(t, 1, len(netconf.Addresses)) require.Equal(t, net.ParseIP("::1"), netconf.Addresses[0].IPNet.IP) - require.Equal(t, 3600, netconf.Addresses[0].PreferredLifetime) - require.Equal(t, 5200, netconf.Addresses[0].ValidLifetime) + require.Equal(t, 3600*time.Second, netconf.Addresses[0].PreferredLifetime) + require.Equal(t, 5200*time.Second, netconf.Addresses[0].ValidLifetime) // check DNSes require.Equal(t, 1, len(netconf.DNSServers)) require.Equal(t, net.ParseIP("fe80::1"), netconf.DNSServers[0]) @@ -212,8 +213,8 @@ func TestGetNetConfFromPacketv4(t *testing.T) { // check addresses require.Equal(t, 1, len(netconf.Addresses)) require.Equal(t, net.ParseIP("10.0.0.1"), netconf.Addresses[0].IPNet.IP) - require.Equal(t, 0, netconf.Addresses[0].PreferredLifetime) - require.Equal(t, 5200, netconf.Addresses[0].ValidLifetime) + require.Equal(t, time.Duration(0), netconf.Addresses[0].PreferredLifetime) + require.Equal(t, 5200*time.Second, netconf.Addresses[0].ValidLifetime) // check DNSes require.Equal(t, 2, len(netconf.DNSServers)) require.Equal(t, net.ParseIP("10.10.0.1").To4(), netconf.DNSServers[0]) -- cgit v1.2.3