diff options
Diffstat (limited to 'dhcpv6/option_iaprefix.go')
-rw-r--r-- | dhcpv6/option_iaprefix.go | 86 |
1 files changed, 48 insertions, 38 deletions
diff --git a/dhcpv6/option_iaprefix.go b/dhcpv6/option_iaprefix.go index bb907b2..750f0cd 100644 --- a/dhcpv6/option_iaprefix.go +++ b/dhcpv6/option_iaprefix.go @@ -8,6 +8,30 @@ import ( "github.com/u-root/u-root/pkg/uio" ) +// PrefixOptions are the options valid for use with IAPrefix option field. +// +// RFC 3633 states that it's just the StatusCode option. +// +// RFC 8415 Appendix C does not list the Status Code option as valid, but it +// does say that the previous text in RFC 8415 Section 21.22 supersedes that +// table. Section 21.22 does mention the Status Code option. +type PrefixOptions struct { + Options +} + +// Status returns the status code associated with this option. +func (po PrefixOptions) Status() *OptStatusCode { + opt := po.Options.GetOne(OptionStatusCode) + if opt == nil { + return nil + } + sc, ok := opt.(*OptStatusCode) + if !ok { + return nil + } + return sc +} + // OptIAPrefix implements the IAPrefix option. // // This module defines the OptIAPrefix structure. @@ -15,9 +39,8 @@ import ( type OptIAPrefix struct { PreferredLifetime time.Duration ValidLifetime time.Duration - prefixLength byte - ipv6Prefix net.IP - Options Options + Prefix *net.IPNet + Options PrefixOptions } func (op *OptIAPrefix) Code() OptionCode { @@ -33,44 +56,22 @@ func (op *OptIAPrefix) ToBytes() []byte { t2 := Duration{op.ValidLifetime} t2.Marshal(buf) - buf.Write8(op.prefixLength) - write16(buf, op.ipv6Prefix) + if op.Prefix != nil { + // Even if Mask is nil, Size will return 0 without panicking. + length, _ := op.Prefix.Mask.Size() + buf.Write8(uint8(length)) + write16(buf, op.Prefix.IP) + } else { + buf.Write8(0) + write16(buf, nil) + } buf.WriteBytes(op.Options.ToBytes()) return buf.Data() } -func (op *OptIAPrefix) PrefixLength() byte { - return op.prefixLength -} - -func (op *OptIAPrefix) SetPrefixLength(pl byte) { - op.prefixLength = pl -} - -// IPv6Prefix returns the ipv6Prefix -func (op *OptIAPrefix) IPv6Prefix() net.IP { - return op.ipv6Prefix -} - -// SetIPv6Prefix sets the ipv6Prefix -func (op *OptIAPrefix) SetIPv6Prefix(p net.IP) { - op.ipv6Prefix = p -} - 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) -} - -// 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 op.Options.GetOne(code) -} - -// DelOption will remove all the options that match a Option code. -func (op *OptIAPrefix) DelOption(code OptionCode) { - op.Options.Del(code) + return fmt.Sprintf("IAPrefix: {PreferredLifetime=%v, ValidLifetime=%v, Prefix=%s, Options=%v}", + op.PreferredLifetime, op.ValidLifetime, op.Prefix, op.Options) } // ParseOptIAPrefix an OptIAPrefix structure from a sequence of bytes. The @@ -85,8 +86,17 @@ func ParseOptIAPrefix(data []byte) (*OptIAPrefix, error) { opt.PreferredLifetime = t1.Duration opt.ValidLifetime = t2.Duration - opt.prefixLength = buf.Read8() - opt.ipv6Prefix = net.IP(buf.CopyN(net.IPv6len)) + length := buf.Read8() + ip := net.IP(buf.CopyN(net.IPv6len)) + + if length == 0 { + opt.Prefix = nil + } else { + opt.Prefix = &net.IPNet{ + Mask: net.CIDRMask(int(length), 128), + IP: ip, + } + } if err := opt.Options.FromBytes(buf.ReadAll()); err != nil { return nil, err } |