summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrea Barberio <insomniac@slackware.it>2019-04-23 09:24:48 +0100
committerAndrea Barberio <insomniac@slackware.it>2019-04-23 20:05:31 +0100
commitb071bdc86a58037f6c745647c97fca202f3caef9 (patch)
treea64975a795bad93f7e58256cfecdb01aaf45067f
parentef6ad8a08ce25eeca699f984c59062c6ca107ee1 (diff)
[dhcpv6] Solicit messages derive default IAID from MAC address
IAID must be set by the client. This patch generates the IAID from the MAC address of the interface. To do so, a new WithIAID modifier is added, the interface of NewSolicitWithCID now requires a hwaddr parameter, and NewAdvertiseFromSolicit copies the IA_NA option from the solicit if present. Signed-off-by: Andrea Barberio <insomniac@slackware.it>
-rw-r--r--dhcpv6/async/client_test.go2
-rw-r--r--dhcpv6/dhcpv6_test.go11
-rw-r--r--dhcpv6/dhcpv6message.go23
-rw-r--r--dhcpv6/dhcpv6relay_test.go1
-rw-r--r--dhcpv6/modifiers.go15
5 files changed, 42 insertions, 10 deletions
diff --git a/dhcpv6/async/client_test.go b/dhcpv6/async/client_test.go
index 9b58112..a3b076c 100644
--- a/dhcpv6/async/client_test.go
+++ b/dhcpv6/async/client_test.go
@@ -26,7 +26,7 @@ func solicit(input string) (*dhcpv6.Message, error) {
Time: dhcpv6.GetTime(),
LinkLayerAddr: mac,
}
- return dhcpv6.NewSolicitWithCID(duid)
+ return dhcpv6.NewSolicitWithCID(duid, mac, dhcpv6.WithIAID([4]byte{1, 2, 3, 4}))
}
// server creates a server which responds with a predefined response
diff --git a/dhcpv6/dhcpv6_test.go b/dhcpv6/dhcpv6_test.go
index d509572..ac44314 100644
--- a/dhcpv6/dhcpv6_test.go
+++ b/dhcpv6/dhcpv6_test.go
@@ -144,6 +144,7 @@ func TestNewAdvertiseFromSolicit(t *testing.T) {
cid := OptClientId{}
s.AddOption(&cid)
duid := Duid{}
+ WithIAID([4]byte{1, 2, 3, 4})(&s)
a, err := NewAdvertiseFromSolicit(&s, WithServerID(duid))
require.NoError(t, err)
@@ -207,7 +208,7 @@ func TestNewMessageTypeSolicitWithCID(t *testing.T) {
LinkLayerAddr: hwAddr,
}
- s, err := NewSolicitWithCID(duid)
+ s, err := NewSolicitWithCID(duid, hwAddr)
require.NoError(t, err)
require.Equal(t, s.Type(), MessageTypeSolicit)
@@ -227,6 +228,14 @@ func TestNewMessageTypeSolicitWithCID(t *testing.T) {
require.Contains(t, opts, OptionDNSRecursiveNameServer)
require.Contains(t, opts, OptionDomainSearchList)
require.Equal(t, len(opts), 2)
+
+ // Check IA_NA
+ iaid := [4]byte{hwAddr[2], hwAddr[3], hwAddr[4], hwAddr[5]}
+ iaNaOption := s.GetOneOption(OptionIANA)
+ require.NotNil(t, iaNaOption)
+ iaNa, ok := iaNaOption.(*OptIANA)
+ require.True(t, ok)
+ require.Equal(t, iaid, iaNa.IaId)
}
func TestIsUsingUEFIArchTypeTrue(t *testing.T) {
diff --git a/dhcpv6/dhcpv6message.go b/dhcpv6/dhcpv6message.go
index 9237c1b..bc23156 100644
--- a/dhcpv6/dhcpv6message.go
+++ b/dhcpv6/dhcpv6message.go
@@ -43,7 +43,7 @@ func GetTime() uint32 {
}
// NewSolicitWithCID creates a new SOLICIT message with CID.
-func NewSolicitWithCID(duid Duid, modifiers ...Modifier) (*Message, error) {
+func NewSolicitWithCID(duid Duid, hwaddr net.HardwareAddr, modifiers ...Modifier) (*Message, error) {
m, err := NewMessage()
if err != nil {
return nil, err
@@ -57,12 +57,13 @@ func NewSolicitWithCID(duid Duid, modifiers ...Modifier) (*Message, error) {
})
m.AddOption(oro)
m.AddOption(&OptElapsedTime{})
- // FIXME use real values for IA_NA
- iaNa := &OptIANA{}
- iaNa.IaId = [4]byte{0xfa, 0xce, 0xb0, 0x0c}
- iaNa.T1 = 0xe10
- iaNa.T2 = 0x1518
- m.AddOption(iaNa)
+ if len(hwaddr) < 4 {
+ return nil, errors.New("short hardware addrss: less than 4 bytes")
+ }
+ l := len(hwaddr)
+ var iaid [4]byte
+ copy(iaid[:], hwaddr[l-4:l])
+ modifiers = append([]Modifier{WithIAID(iaid)}, modifiers...)
// Apply modifiers
for _, mod := range modifiers {
mod(m)
@@ -79,7 +80,7 @@ func NewSolicit(ifaceHWAddr net.HardwareAddr, modifiers ...Modifier) (*Message,
Time: GetTime(),
LinkLayerAddr: ifaceHWAddr,
}
- return NewSolicitWithCID(duid, modifiers...)
+ return NewSolicitWithCID(duid, ifaceHWAddr, modifiers...)
}
// NewAdvertiseFromSolicit creates a new ADVERTISE packet based on an SOLICIT packet.
@@ -101,6 +102,12 @@ func NewAdvertiseFromSolicit(sol *Message, modifiers ...Modifier) (*Message, err
return nil, errors.New("Client ID cannot be nil in SOLICIT when building ADVERTISE")
}
adv.AddOption(cid)
+ // add IA_NA
+ iaNa := sol.GetOneOption(OptionIANA)
+ if iaNa == nil {
+ return nil, fmt.Errorf("IA_NA cannot be nil in SOLICIT when building ADVERTISE")
+ }
+ adv.AddOption(iaNa)
// apply modifiers
for _, mod := range modifiers {
diff --git a/dhcpv6/dhcpv6relay_test.go b/dhcpv6/dhcpv6relay_test.go
index 270dd52..6c7f96f 100644
--- a/dhcpv6/dhcpv6relay_test.go
+++ b/dhcpv6/dhcpv6relay_test.go
@@ -90,6 +90,7 @@ func TestNewRelayRepFromRelayForw(t *testing.T) {
s, err := NewMessage()
require.NoError(t, err)
s.AddOption(&OptClientId{})
+ WithIAID([4]byte{1, 2, 3, 4})(s)
orm := OptRelayMsg{}
orm.SetRelayMessage(s)
rf.AddOption(&orm)
diff --git a/dhcpv6/modifiers.go b/dhcpv6/modifiers.go
index eaa370d..200a602 100644
--- a/dhcpv6/modifiers.go
+++ b/dhcpv6/modifiers.go
@@ -77,6 +77,21 @@ func WithIANA(addrs ...OptIAAddress) Modifier {
}
}
+// WithIAID updates an OptIANA option with the provided IAID
+func WithIAID(iaid [4]byte) Modifier {
+ return func(d DHCPv6) {
+ opt := d.GetOneOption(OptionIANA)
+ if opt == nil {
+ opt = &OptIANA{
+ Options: Options{},
+ }
+ }
+ iaNa := opt.(*OptIANA)
+ copy(iaNa.IaId[:], iaid[:])
+ d.UpdateOption(iaNa)
+ }
+}
+
// WithDNS adds or updates an OptDNSRecursiveNameServer
func WithDNS(dnses ...net.IP) Modifier {
return func(d DHCPv6) {