diff options
-rw-r--r-- | dhcpv6/option_iaaddress.go | 2 | ||||
-rw-r--r-- | dhcpv6/option_iaprefix.go | 80 | ||||
-rw-r--r-- | dhcpv6/option_iaprefix_test.go | 29 | ||||
-rw-r--r-- | dhcpv6/option_prefixdelegation_test.go | 7 |
4 files changed, 56 insertions, 62 deletions
diff --git a/dhcpv6/option_iaaddress.go b/dhcpv6/option_iaaddress.go index 0500d83..6f430db 100644 --- a/dhcpv6/option_iaaddress.go +++ b/dhcpv6/option_iaaddress.go @@ -47,7 +47,7 @@ func (op *OptIAAddress) Length() int { func (op *OptIAAddress) String() string { return fmt.Sprintf("OptIAAddress{ipv6addr=%v, preferredlifetime=%v, validlifetime=%v, options=%v}", - net.IP(op.IPv6Addr[:]), op.PreferredLifetime, op.ValidLifetime, op.Options) + op.IPv6Addr, op.PreferredLifetime, op.ValidLifetime, op.Options) } // ParseOptIAAddress builds an OptIAAddress structure from a sequence diff --git a/dhcpv6/option_iaprefix.go b/dhcpv6/option_iaprefix.go index 1f68789..8a39531 100644 --- a/dhcpv6/option_iaprefix.go +++ b/dhcpv6/option_iaprefix.go @@ -10,11 +10,11 @@ import ( ) type OptIAPrefix struct { - preferredLifetime uint32 - validLifetime uint32 + PreferredLifetime uint32 + ValidLifetime uint32 prefixLength byte - ipv6Prefix [16]byte - options []byte + ipv6Prefix net.IP + Options []Option } func (op *OptIAPrefix) Code() OptionCode { @@ -25,30 +25,16 @@ func (op *OptIAPrefix) ToBytes() []byte { buf := make([]byte, 12) binary.BigEndian.PutUint16(buf[0:2], uint16(OptionIAPrefix)) binary.BigEndian.PutUint16(buf[2:4], uint16(op.Length())) - binary.BigEndian.PutUint32(buf[4:8], op.preferredLifetime) - binary.BigEndian.PutUint32(buf[8:12], op.validLifetime) + binary.BigEndian.PutUint32(buf[4:8], op.PreferredLifetime) + binary.BigEndian.PutUint32(buf[8:12], op.ValidLifetime) buf = append(buf, op.prefixLength) - buf = append(buf, op.ipv6Prefix[:]...) - buf = append(buf, op.options...) + buf = append(buf, op.ipv6Prefix...) + for _, opt := range op.Options { + buf = append(buf, opt.ToBytes()...) + } return buf } -func (op *OptIAPrefix) PreferredLifetime() uint32 { - return op.preferredLifetime -} - -func (op *OptIAPrefix) SetPreferredLifetime(pl uint32) { - op.preferredLifetime = pl -} - -func (op *OptIAPrefix) ValidLifetime() uint32 { - return op.validLifetime -} - -func (op *OptIAPrefix) SetValidLifetime(vl uint32) { - op.validLifetime = vl -} - func (op *OptIAPrefix) PrefixLength() byte { return op.prefixLength } @@ -57,42 +43,56 @@ func (op *OptIAPrefix) SetPrefixLength(pl byte) { op.prefixLength = pl } -func (op *OptIAPrefix) IPv6Prefix() []byte { - return op.ipv6Prefix[:] +// IPv6Prefix returns the ipv6Prefix +func (op *OptIAPrefix) IPv6Prefix() net.IP { + return op.ipv6Prefix } -func (op *OptIAPrefix) SetIPv6Prefix(p [16]byte) { +// SetIPv6Prefix sets the ipv6Prefix +func (op *OptIAPrefix) SetIPv6Prefix(p net.IP) { op.ipv6Prefix = p } -func (op *OptIAPrefix) Options() []byte { - return op.options +// Length returns the option length +func (op *OptIAPrefix) Length() int { + opLen := 25 + for _, opt := range op.Options { + opLen += 4 + opt.Length() + } + return opLen } -func (op *OptIAPrefix) SetOptions(options []byte) { - op.options = options +func (op *OptIAPrefix) String() string { + return fmt.Sprintf("OptIAPrefix{preferredlifetime=%v, validlifetime=%v, prefixlength=%v, ipv6prefix=%v, options=%v}", + op.PreferredLifetime, op.ValidLifetime, op.PrefixLength(), op.IPv6Prefix(), op.Options) } -func (op *OptIAPrefix) Length() int { - return 25 + len(op.options) +// GetOneOption will get an option of the give type from the Options field, if +// it is present. It will return `nil` otherwise +func (op *OptIAPrefix) GetOneOption(code OptionCode) Option { + return getOption(op.Options, code) } -func (op *OptIAPrefix) String() string { - return fmt.Sprintf("OptIAPrefix{preferredlifetime=%v, validlifetime=%v, prefixlength=%v, ipv6prefix=%v, options=%v}", - op.preferredLifetime, op.validLifetime, op.prefixLength, net.IP(op.ipv6Prefix[:]), op.options) +// DelOption will remove all the options that match a Option code. +func (op *OptIAPrefix) DelOption(code OptionCode) { + op.Options = delOption(op.Options, code) } // build an OptIAPrefix structure from a sequence of bytes. // The input data does not include option code and length bytes. func ParseOptIAPrefix(data []byte) (*OptIAPrefix, error) { + var err error opt := OptIAPrefix{} if len(data) < 25 { return nil, fmt.Errorf("Invalid IA for Prefix Delegation data length. Expected at least 25 bytes, got %v", len(data)) } - opt.preferredLifetime = binary.BigEndian.Uint32(data[:4]) - opt.validLifetime = binary.BigEndian.Uint32(data[4:8]) + opt.PreferredLifetime = binary.BigEndian.Uint32(data[:4]) + opt.ValidLifetime = binary.BigEndian.Uint32(data[4:8]) opt.prefixLength = data[8] - copy(opt.ipv6Prefix[:], data[9:25]) - copy(opt.options, data[25:]) + opt.ipv6Prefix = net.IP(data[9:25]) + opt.Options, err = OptionsFromBytes(data[25:]) + if err != nil { + return nil, err + } return &opt, nil } diff --git a/dhcpv6/option_iaprefix_test.go b/dhcpv6/option_iaprefix_test.go index f7b5b6b..2c4dea4 100644 --- a/dhcpv6/option_iaprefix_test.go +++ b/dhcpv6/option_iaprefix_test.go @@ -14,15 +14,16 @@ func TestOptIAPrefix(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, 1, // ipv6Prefix + 0, 8, 0, 2, 0xaa, 0xbb, // options } opt, err := ParseOptIAPrefix(buf) if err != nil { t.Fatal(err) } - if pl := opt.PreferredLifetime(); pl != 0xaabbccdd { + if pl := opt.PreferredLifetime; pl != 0xaabbccdd { t.Fatalf("Invalid Preferred Lifetime. Expected 0xaabbccdd, got %v", pl) } - if vl := opt.ValidLifetime(); vl != 0xeeff0011 { + if vl := opt.ValidLifetime; vl != 0xeeff0011 { t.Fatalf("Invalid Valid Lifetime. Expected 0xeeff0011, got %v", vl) } if pr := opt.PrefixLength(); pr != 36 { @@ -31,6 +32,9 @@ func TestOptIAPrefix(t *testing.T) { if ip := opt.IPv6Prefix(); !bytes.Equal(ip, net.IPv6loopback) { t.Fatalf("Invalid Prefix Length. Expected %v, got %v", net.IPv6loopback, ip) } + if opt.Length() != len(buf) { + t.Fatalf("Invalid Option Length. Expected %v, got %v", len(buf), opt.Length()) + } } func TestOptIAPrefixToBytes(t *testing.T) { @@ -39,14 +43,17 @@ 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 } expected := []byte{00, 26, 00, byte(len(buf))} expected = append(expected, buf...) opt := OptIAPrefix{ - preferredLifetime: 0xaabbccdd, - validLifetime: 0xeeff0011, + PreferredLifetime: 0xaabbccdd, + ValidLifetime: 0xeeff0011, prefixLength: 36, + ipv6Prefix: net.IPv6zero, } + opt.Options = append(opt.Options, &OptElapsedTime{ElapsedTime: 0xaabb}) toBytes := opt.ToBytes() if !bytes.Equal(toBytes, expected) { t.Fatalf("Invalid ToBytes result. Expected %v, got %v", expected, toBytes) @@ -65,20 +72,6 @@ func TestOptIAPrefixParseInvalidTooShort(t *testing.T) { } } -func TestOptIAPrefixSetGetOptions(t *testing.T) { - opt := OptIAPrefix{ - preferredLifetime: 0xaabbccdd, - validLifetime: 0xeeff0011, - } - expected := []byte{ - 0, 8, 0, 2, 0xaa, 0xbb, // options - } - - require.Equal(t, []byte(nil), opt.Options(), "Options() should be blank by default") - opt.SetOptions(expected) - require.Equal(t, expected, opt.Options(), "Options() did not contain the correct data") -} - func TestOptIAPrefixString(t *testing.T) { buf := []byte{ 0xaa, 0xbb, 0xcc, 0xdd, // preferredLifetime diff --git a/dhcpv6/option_prefixdelegation_test.go b/dhcpv6/option_prefixdelegation_test.go index cb90e25..93044fe 100644 --- a/dhcpv6/option_prefixdelegation_test.go +++ b/dhcpv6/option_prefixdelegation_test.go @@ -1,6 +1,7 @@ package dhcpv6 import ( + "net" "testing" "github.com/stretchr/testify/require" @@ -106,10 +107,10 @@ func TestOptIAForPrefixDelegationDelOption(t *testing.T) { func TestOptIAForPrefixDelegationToBytes(t *testing.T) { oaddr := OptIAPrefix{} - oaddr.SetPreferredLifetime(0xaabbccdd) - oaddr.SetValidLifetime(0xeeff0011) + oaddr.PreferredLifetime = 0xaabbccdd + oaddr.ValidLifetime = 0xeeff0011 oaddr.SetPrefixLength(36) - oaddr.SetIPv6Prefix([16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) + oaddr.SetIPv6Prefix(net.IPv6loopback) opt := OptIAForPrefixDelegation{} opt.IaId = [4]byte{1, 2, 3, 4} |