diff options
author | Andrea Barberio <insomniac@slackware.it> | 2019-04-23 09:24:48 +0100 |
---|---|---|
committer | Andrea Barberio <insomniac@slackware.it> | 2019-04-23 20:05:31 +0100 |
commit | b071bdc86a58037f6c745647c97fca202f3caef9 (patch) | |
tree | a64975a795bad93f7e58256cfecdb01aaf45067f | |
parent | ef6ad8a08ce25eeca699f984c59062c6ca107ee1 (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.go | 2 | ||||
-rw-r--r-- | dhcpv6/dhcpv6_test.go | 11 | ||||
-rw-r--r-- | dhcpv6/dhcpv6message.go | 23 | ||||
-rw-r--r-- | dhcpv6/dhcpv6relay_test.go | 1 | ||||
-rw-r--r-- | dhcpv6/modifiers.go | 15 |
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) { |