summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--dhcpv6/modifiers.go4
-rw-r--r--dhcpv6/option_nontemporaryaddress.go57
-rw-r--r--dhcpv6/option_nontemporaryaddress_test.go50
3 files changed, 70 insertions, 41 deletions
diff --git a/dhcpv6/modifiers.go b/dhcpv6/modifiers.go
index 14bfe51..ce5ce97 100644
--- a/dhcpv6/modifiers.go
+++ b/dhcpv6/modifiers.go
@@ -63,7 +63,7 @@ func WithIANA(addrs ...OptIAAddress) Modifier {
iana = &OptIANA{}
}
for _, addr := range addrs {
- iana.AddOption(&addr)
+ iana.Options.Add(&addr)
}
msg.UpdateOption(iana)
}
@@ -77,7 +77,7 @@ func WithIAID(iaid [4]byte) Modifier {
iana := msg.Options.OneIANA()
if iana == nil {
iana = &OptIANA{
- Options: Options{},
+ Options: IdentityOptions{Options: []Option{}},
}
}
copy(iana.IaId[:], iaid[:])
diff --git a/dhcpv6/option_nontemporaryaddress.go b/dhcpv6/option_nontemporaryaddress.go
index 3ea46fe..01971f8 100644
--- a/dhcpv6/option_nontemporaryaddress.go
+++ b/dhcpv6/option_nontemporaryaddress.go
@@ -25,6 +25,45 @@ func (d *Duration) Unmarshal(buf *uio.Lexer) {
d.Duration = time.Duration(t) * time.Second
}
+// IdentityOptions implement the options allowed for IA_NA and IA_TA messages.
+//
+// The allowed options are identified in RFC 3315 Appendix B.
+type IdentityOptions struct {
+ Options
+}
+
+// Address returns the addresses assigned to the identity.
+func (io IdentityOptions) Address() []*OptIAAddress {
+ opts := io.Options.Get(OptionIAAddr)
+ var iaAddrs []*OptIAAddress
+ for _, o := range opts {
+ iaAddrs = append(iaAddrs, o.(*OptIAAddress))
+ }
+ return iaAddrs
+}
+
+// OneAddress returns one address (of potentially many) assigned to the identity.
+func (io IdentityOptions) OneAddress() *OptIAAddress {
+ a := io.Address()
+ if len(a) == 0 {
+ return nil
+ }
+ return a[0]
+}
+
+// Status returns the status code associated with this option.
+func (io IdentityOptions) Status() *OptStatusCode {
+ opt := io.Options.GetOne(OptionStatusCode)
+ if opt == nil {
+ return nil
+ }
+ sc, ok := opt.(*OptStatusCode)
+ if !ok {
+ return nil
+ }
+ return sc
+}
+
// OptIANA implements the identity association for non-temporary addresses
// option.
//
@@ -34,7 +73,7 @@ type OptIANA struct {
IaId [4]byte
T1 time.Duration
T2 time.Duration
- Options Options
+ Options IdentityOptions
}
func (op *OptIANA) Code() OptionCode {
@@ -58,22 +97,6 @@ func (op *OptIANA) String() string {
op.IaId, op.T1, op.T2, op.Options)
}
-// AddOption adds an option at the end of the IA_NA options
-func (op *OptIANA) AddOption(opt Option) {
- op.Options.Add(opt)
-}
-
-// GetOneOption will get an option of the give type from the Options field, if
-// it is present. It will return `nil` otherwise
-func (op *OptIANA) GetOneOption(code OptionCode) Option {
- return op.Options.GetOne(code)
-}
-
-// DelOption will remove all the options that match a Option code.
-func (op *OptIANA) DelOption(code OptionCode) {
- op.Options.Del(code)
-}
-
// ParseOptIANA builds an OptIANA structure from a sequence of bytes. The
// input data does not include option code and length bytes.
func ParseOptIANA(data []byte) (*OptIANA, error) {
diff --git a/dhcpv6/option_nontemporaryaddress_test.go b/dhcpv6/option_nontemporaryaddress_test.go
index ceee9ec..50cb11b 100644
--- a/dhcpv6/option_nontemporaryaddress_test.go
+++ b/dhcpv6/option_nontemporaryaddress_test.go
@@ -46,16 +46,16 @@ func TestOptIANAGetOneOption(t *testing.T) {
IPv6Addr: net.ParseIP("::1"),
}
opt := OptIANA{
- Options: []Option{OptElapsedTime(0), oaddr},
+ Options: IdentityOptions{[]Option{&OptStatusCode{}, oaddr}},
}
- require.Equal(t, oaddr, opt.GetOneOption(OptionIAAddr))
+ require.Equal(t, oaddr, opt.Options.OneAddress())
}
func TestOptIANAAddOption(t *testing.T) {
opt := OptIANA{}
- opt.AddOption(OptElapsedTime(0))
- require.Equal(t, 1, len(opt.Options))
- require.Equal(t, OptionElapsedTime, opt.Options[0].Code())
+ opt.Options.Add(OptElapsedTime(0))
+ require.Equal(t, 1, len(opt.Options.Options))
+ require.Equal(t, OptionElapsedTime, opt.Options.Options[0].Code())
}
func TestOptIANAGetOneOptionMissingOpt(t *testing.T) {
@@ -63,28 +63,34 @@ func TestOptIANAGetOneOptionMissingOpt(t *testing.T) {
IPv6Addr: net.ParseIP("::1"),
}
opt := OptIANA{
- Options: []Option{OptElapsedTime(0), oaddr},
+ Options: IdentityOptions{[]Option{&OptStatusCode{}, oaddr}},
}
- require.Equal(t, nil, opt.GetOneOption(OptionDNSRecursiveNameServer))
+ require.Equal(t, nil, opt.Options.GetOne(OptionDNSRecursiveNameServer))
}
func TestOptIANADelOption(t *testing.T) {
- optiana1 := OptIANA{}
- optiana2 := OptIANA{}
optiaaddr := OptIAAddress{}
optsc := OptStatusCode{}
- optiana1.Options = append(optiana1.Options, &optsc)
- optiana1.Options = append(optiana1.Options, &optiaaddr)
- optiana1.Options = append(optiana1.Options, &optiaaddr)
- optiana1.DelOption(OptionIAAddr)
- require.Equal(t, optiana1.Options, Options{&optsc})
+ iana1 := OptIANA{
+ Options: IdentityOptions{[]Option{
+ &optsc,
+ &optiaaddr,
+ &optiaaddr,
+ }},
+ }
+ iana1.Options.Del(OptionIAAddr)
+ require.Equal(t, iana1.Options.Options, Options{&optsc})
- optiana2.Options = append(optiana2.Options, &optiaaddr)
- optiana2.Options = append(optiana2.Options, &optsc)
- optiana2.Options = append(optiana2.Options, &optiaaddr)
- optiana2.DelOption(OptionIAAddr)
- require.Equal(t, optiana2.Options, Options{&optsc})
+ iana2 := OptIANA{
+ Options: IdentityOptions{[]Option{
+ &optiaaddr,
+ &optsc,
+ &optiaaddr,
+ }},
+ }
+ iana2.Options.Del(OptionIAAddr)
+ require.Equal(t, iana2.Options.Options, Options{&optsc})
}
func TestOptIANAToBytes(t *testing.T) {
@@ -92,9 +98,9 @@ func TestOptIANAToBytes(t *testing.T) {
IaId: [4]byte{1, 2, 3, 4},
T1: 12345 * time.Second,
T2: 54321 * time.Second,
- Options: []Option{
+ Options: IdentityOptions{[]Option{
OptElapsedTime(10 * time.Millisecond),
- },
+ }},
}
expected := []byte{
1, 2, 3, 4, // IA ID
@@ -128,7 +134,7 @@ func TestOptIANAString(t *testing.T) {
)
require.Contains(
t, str,
- "options=[",
+ "options={",
"String() should return a list of options",
)
}