summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--dhcpv6/dhcpv6_test.go21
-rw-r--r--dhcpv6/dhcpv6message.go11
-rw-r--r--dhcpv6/dhcpv6relay_test.go2
-rw-r--r--dhcpv6/iputils.go5
-rw-r--r--dhcpv6/modifiers.go3
-rw-r--r--dhcpv6/modifiers_test.go6
-rw-r--r--dhcpv6/option_clientid.go31
-rw-r--r--dhcpv6/option_clientid_test.go34
-rw-r--r--dhcpv6/options.go2
9 files changed, 55 insertions, 60 deletions
diff --git a/dhcpv6/dhcpv6_test.go b/dhcpv6/dhcpv6_test.go
index b23a858..6f476a1 100644
--- a/dhcpv6/dhcpv6_test.go
+++ b/dhcpv6/dhcpv6_test.go
@@ -165,11 +165,9 @@ func TestNewAdvertiseFromSolicit(t *testing.T) {
MessageType: MessageTypeSolicit,
TransactionID: TransactionID{0xa, 0xb, 0xc},
}
- cid := OptClientId{}
- s.AddOption(&cid)
- duid := Duid{}
+ s.AddOption(OptClientID(Duid{}))
- a, err := NewAdvertiseFromSolicit(&s, WithServerID(duid))
+ a, err := NewAdvertiseFromSolicit(&s, WithServerID(Duid{}))
require.NoError(t, err)
require.Equal(t, a.TransactionID, s.TransactionID)
require.Equal(t, a.Type(), MessageTypeAdvertise)
@@ -180,11 +178,10 @@ func TestNewReplyFromMessage(t *testing.T) {
TransactionID: TransactionID{0xa, 0xb, 0xc},
MessageType: MessageTypeConfirm,
}
- cid := OptClientId{}
- msg.AddOption(&cid)
+ var duid Duid
+ msg.AddOption(OptClientID(duid))
sid := OptServerId{}
- duid := Duid{}
- sid.Sid = duid
+ sid.Sid = Duid{}
msg.AddOption(&sid)
rep, err := NewReplyFromMessage(&msg, WithServerID(duid))
@@ -242,11 +239,9 @@ func TestNewMessageTypeSolicit(t *testing.T) {
require.Equal(t, s.Type(), MessageTypeSolicit)
// Check CID
- cidOption := s.GetOneOption(OptionClientID)
- require.NotNil(t, cidOption)
- cid, ok := cidOption.(*OptClientId)
- require.True(t, ok)
- require.Equal(t, cid.Cid, duid)
+ cduid := s.Options.ClientID()
+ require.NotNil(t, cduid)
+ require.Equal(t, cduid, &duid)
// Check ORO
oroOption := s.GetOneOption(OptionORO)
diff --git a/dhcpv6/dhcpv6message.go b/dhcpv6/dhcpv6message.go
index d67882a..00452dc 100644
--- a/dhcpv6/dhcpv6message.go
+++ b/dhcpv6/dhcpv6message.go
@@ -29,6 +29,15 @@ func (mo MessageOptions) ArchTypes() iana.Archs {
return opt.(*optClientArchType).Archs
}
+// ClientID returns the client identifier option.
+func (mo MessageOptions) ClientID() *Duid {
+ opt := mo.GetOne(OptionClientID)
+ if opt == nil {
+ return nil
+ }
+ return &opt.(*optClientID).Duid
+}
+
// Message represents a DHCPv6 Message as defined by RFC 3315 Section 6.
type Message struct {
MessageType MessageType
@@ -72,7 +81,7 @@ func NewSolicit(hwaddr net.HardwareAddr, modifiers ...Modifier) (*Message, error
return nil, err
}
m.MessageType = MessageTypeSolicit
- m.AddOption(&OptClientId{Cid: duid})
+ m.AddOption(OptClientID(duid))
oro := new(OptRequestedOption)
oro.SetRequestedOptions([]OptionCode{
OptionDNSRecursiveNameServer,
diff --git a/dhcpv6/dhcpv6relay_test.go b/dhcpv6/dhcpv6relay_test.go
index 4070f54..773c047 100644
--- a/dhcpv6/dhcpv6relay_test.go
+++ b/dhcpv6/dhcpv6relay_test.go
@@ -91,7 +91,7 @@ func TestNewRelayRepFromRelayForw(t *testing.T) {
// create the inner message
s, err := NewMessage()
require.NoError(t, err)
- s.AddOption(&OptClientId{})
+ s.AddOption(OptClientID(Duid{}))
orm := OptRelayMsg{}
orm.SetRelayMessage(s)
rf.AddOption(&orm)
diff --git a/dhcpv6/iputils.go b/dhcpv6/iputils.go
index b8c5876..9c18da2 100644
--- a/dhcpv6/iputils.go
+++ b/dhcpv6/iputils.go
@@ -83,11 +83,10 @@ func ExtractMAC(packet DHCPv6) (net.HardwareAddr, error) {
return nil, err
}
}
- optclientid := msg.GetOneOption(OptionClientID)
- if optclientid == nil {
+ duid := msg.(*Message).Options.ClientID()
+ if duid == nil {
return nil, fmt.Errorf("client ID not found in packet")
}
- duid := optclientid.(*OptClientId).Cid
if duid.LinkLayerAddr == nil {
return nil, fmt.Errorf("failed to extract MAC")
}
diff --git a/dhcpv6/modifiers.go b/dhcpv6/modifiers.go
index d5e24c0..4d00a0c 100644
--- a/dhcpv6/modifiers.go
+++ b/dhcpv6/modifiers.go
@@ -11,8 +11,7 @@ import (
// WithClientID adds a client ID option to a DHCPv6 packet
func WithClientID(duid Duid) Modifier {
return func(d DHCPv6) {
- cid := OptClientId{Cid: duid}
- d.UpdateOption(&cid)
+ d.UpdateOption(OptClientID(duid))
}
}
diff --git a/dhcpv6/modifiers_test.go b/dhcpv6/modifiers_test.go
index ec8ff0b..ff3a87a 100644
--- a/dhcpv6/modifiers_test.go
+++ b/dhcpv6/modifiers_test.go
@@ -17,10 +17,8 @@ func TestWithClientID(t *testing.T) {
}
m, err := NewMessage(WithClientID(duid))
require.NoError(t, err)
- opt := m.GetOneOption(OptionClientID)
- require.NotNil(t, opt)
- cid := opt.(*OptClientId)
- require.Equal(t, cid.Cid, duid)
+ cid := m.Options.ClientID()
+ require.Equal(t, cid, &duid)
}
func TestWithServerID(t *testing.T) {
diff --git a/dhcpv6/option_clientid.go b/dhcpv6/option_clientid.go
index 200d1a6..0941bcc 100644
--- a/dhcpv6/option_clientid.go
+++ b/dhcpv6/option_clientid.go
@@ -4,36 +4,31 @@ import (
"fmt"
)
-// OptClientId represents a Client ID option
-//
-// This module defines the OptClientId and DUID structures.
-// https://www.ietf.org/rfc/rfc3315.txt
-type OptClientId struct {
- Cid Duid
+// OptClientID represents a Client Identifier option as defined by RFC 3315
+// Section 22.2.
+func OptClientID(d Duid) Option {
+ return &optClientID{d}
}
-func (op *OptClientId) Code() OptionCode {
- return OptionClientID
+type optClientID struct {
+ Duid
}
-// ToBytes marshals the Client ID option as defined by RFC 3315, Section 22.2.
-func (op *OptClientId) ToBytes() []byte {
- return op.Cid.ToBytes()
+func (*optClientID) Code() OptionCode {
+ return OptionClientID
}
-func (op *OptClientId) String() string {
- return fmt.Sprintf("OptClientId{cid=%v}", op.Cid.String())
+func (op *optClientID) String() string {
+ return fmt.Sprintf("ClientID: %v", op.Duid.String())
}
-// ParseOptClientId builds an OptClientId structure from a sequence
+// parseOptClientID builds an OptClientId structure from a sequence
// of bytes. The input data does not include option code and length
// bytes.
-func ParseOptClientId(data []byte) (*OptClientId, error) {
- var opt OptClientId
+func parseOptClientID(data []byte) (*optClientID, error) {
cid, err := DuidFromBytes(data)
if err != nil {
return nil, err
}
- opt.Cid = *cid
- return &opt, nil
+ return &optClientID{*cid}, nil
}
diff --git a/dhcpv6/option_clientid_test.go b/dhcpv6/option_clientid_test.go
index 69a60d1..2f1f1f0 100644
--- a/dhcpv6/option_clientid_test.go
+++ b/dhcpv6/option_clientid_test.go
@@ -8,27 +8,27 @@ import (
"github.com/stretchr/testify/require"
)
-func TestParseOptClientId(t *testing.T) {
+func TestParseOptClientID(t *testing.T) {
data := []byte{
0, 3, // DUID_LL
0, 1, // hwtype ethernet
0, 1, 2, 3, 4, 5, // hw addr
}
- opt, err := ParseOptClientId(data)
+ opt, err := parseOptClientID(data)
require.NoError(t, err)
- require.Equal(t, DUID_LL, opt.Cid.Type)
- require.Equal(t, iana.HWTypeEthernet, opt.Cid.HwType)
- require.Equal(t, net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5}), opt.Cid.LinkLayerAddr)
+ require.Equal(t, DUID_LL, opt.Type)
+ require.Equal(t, iana.HWTypeEthernet, opt.HwType)
+ require.Equal(t, net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5}), opt.LinkLayerAddr)
}
func TestOptClientIdToBytes(t *testing.T) {
- opt := OptClientId{
- Cid: Duid{
+ opt := OptClientID(
+ Duid{
Type: DUID_LL,
HwType: iana.HWTypeEthernet,
LinkLayerAddr: net.HardwareAddr([]byte{5, 4, 3, 2, 1, 0}),
},
- }
+ )
expected := []byte{
0, 3, // DUID_LL
0, 1, // hwtype ethernet
@@ -43,42 +43,42 @@ func TestOptClientIdDecodeEncode(t *testing.T) {
0, 1, // hwtype ethernet
5, 4, 3, 2, 1, 0, // hw addr
}
- opt, err := ParseOptClientId(data)
+ opt, err := parseOptClientID(data)
require.NoError(t, err)
require.Equal(t, data, opt.ToBytes())
}
func TestOptionClientId(t *testing.T) {
- opt := OptClientId{
- Cid: Duid{
+ opt := OptClientID(
+ Duid{
Type: DUID_LL,
HwType: iana.HWTypeEthernet,
LinkLayerAddr: net.HardwareAddr([]byte{0xde, 0xad, 0, 0, 0xbe, 0xef}),
},
- }
+ )
require.Equal(t, OptionClientID, opt.Code())
require.Contains(
t,
opt.String(),
- "cid=DUID{type=DUID-LL hwtype=Ethernet hwaddr=de:ad:00:00:be:ef}",
+ "ClientID: DUID{type=DUID-LL hwtype=Ethernet hwaddr=de:ad:00:00:be:ef}",
"String() should contain the correct cid output",
)
}
-func TestOptClientIdParseOptClientIdBogusDUID(t *testing.T) {
+func TestOptClientIdparseOptClientIDBogusDUID(t *testing.T) {
data := []byte{
0, 4, // DUID_UUID
1, 2, 3, 4, 5, 6, 7, 8, 9, // a UUID should be 18 bytes not 17
10, 11, 12, 13, 14, 15, 16, 17,
}
- _, err := ParseOptClientId(data)
+ _, err := parseOptClientID(data)
require.Error(t, err, "A truncated OptClientId DUID should return an error")
}
-func TestOptClientIdParseOptClientIdInvalidTooShort(t *testing.T) {
+func TestOptClientIdparseOptClientIDInvalidTooShort(t *testing.T) {
data := []byte{
0, // truncated: DUIDs are at least 2 bytes
}
- _, err := ParseOptClientId(data)
+ _, err := parseOptClientID(data)
require.Error(t, err, "A truncated OptClientId should return an error")
}
diff --git a/dhcpv6/options.go b/dhcpv6/options.go
index bf37600..ef7c23a 100644
--- a/dhcpv6/options.go
+++ b/dhcpv6/options.go
@@ -40,7 +40,7 @@ func ParseOption(code OptionCode, optData []byte) (Option, error) {
)
switch code {
case OptionClientID:
- opt, err = ParseOptClientId(optData)
+ opt, err = parseOptClientID(optData)
case OptionServerID:
opt, err = ParseOptServerId(optData)
case OptionIANA: