From 1f5b1f1e690f046afd6fe2b1777f68beec555c9c Mon Sep 17 00:00:00 2001 From: Pablo Mazzini Date: Thu, 12 Jul 2018 17:59:09 +0200 Subject: add GetInnerRelay --- dhcpv6/dhcpv6relay.go | 36 +++++++++++++++++++----------------- dhcpv6/dhcpv6relay_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 17 deletions(-) (limited to 'dhcpv6') diff --git a/dhcpv6/dhcpv6relay.go b/dhcpv6/dhcpv6relay.go index fb2a0c1..527eddc 100644 --- a/dhcpv6/dhcpv6relay.go +++ b/dhcpv6/dhcpv6relay.go @@ -158,28 +158,30 @@ func (d *DHCPv6Relay) GetInnerMessage() (DHCPv6, error) { } } -// GetInnerPeerAddr returns the peer address in the inner most relay info -// header, this is typically the IP address of the client making the request. -func (r *DHCPv6Relay) GetInnerPeerAddr() (net.IP, error) { - var ( - p DHCPv6 - err error - ) - p = r - hops := r.HopCount() - addr := r.PeerAddr() - for i := uint8(0); i < hops; i++ { - p, err = DecapsulateRelay(p) +// Recurse into a relay message and extract and return the inner DHCPv6Relay. +// Return nil if none found (e.g. not a relay message). +func (r *DHCPv6Relay) GetInnerRelay() (DHCPv6, error) { + p := r + for { + d, err := DecapsulateRelay(p) if err != nil { return nil, err } - if p.IsRelay() { - addr = p.(*DHCPv6Relay).PeerAddr() - } else { - return nil, fmt.Errorf("Wrong Hop count") + if !d.IsRelay() { + return p, nil } + p = d.(*DHCPv6Relay) + } +} + +// GetInnerPeerAddr returns the peer address in the inner most relay info +// header, this is typically the IP address of the client making the request. +func (r *DHCPv6Relay) GetInnerPeerAddr() (net.IP, error) { + p, err := r.GetInnerRelay() + if err != nil { + return nil, err } - return addr, nil + return p.(*DHCPv6Relay).PeerAddr(), nil } // NewRelayReplFromRelayForw creates a RELAY_REPL packet based on a RELAY_FORW diff --git a/dhcpv6/dhcpv6relay_test.go b/dhcpv6/dhcpv6relay_test.go index e08e6a4..3effb35 100644 --- a/dhcpv6/dhcpv6relay_test.go +++ b/dhcpv6/dhcpv6relay_test.go @@ -107,6 +107,31 @@ func TestDHCPv6RelayToBytes(t *testing.T) { } } +func TestGetInnerRelay(t *testing.T) { + m := DHCPv6Message{} + r1, err := EncapsulateRelay(&m, RELAY_FORW, net.IPv6linklocalallnodes, net.IPv6interfacelocalallnodes) + require.NoError(t, err) + r2, err := EncapsulateRelay(r1, RELAY_FORW, net.IPv6loopback, net.IPv6linklocalallnodes) + require.NoError(t, err) + r3, err := EncapsulateRelay(r2, RELAY_FORW, net.IPv6unspecified, net.IPv6linklocalallrouters) + require.NoError(t, err) + + relay3, ok := r3.(*DHCPv6Relay) + require.True(t, ok) + + ir, err := relay3.GetInnerRelay() + require.NoError(t, err) + relay, ok := ir.(*DHCPv6Relay) + require.True(t, ok) + require.Equal(t, relay.HopCount(), uint8(0)) + require.Equal(t, relay.LinkAddr(), net.IPv6linklocalallnodes) + require.Equal(t, relay.PeerAddr(), net.IPv6interfacelocalallnodes) + + innerPeerAddr, err := relay3.GetInnerPeerAddr() + require.NoError(t, err) + require.Equal(t, innerPeerAddr, net.IPv6interfacelocalallnodes) +} + func TestNewRelayRepFromRelayForw(t *testing.T) { rf := DHCPv6Relay{} rf.SetMessageType(RELAY_FORW) -- cgit v1.2.3 From 6ebda8509292d4f9091c36cdcf169a322bc173da Mon Sep 17 00:00:00 2001 From: Pablo Mazzini Date: Thu, 12 Jul 2018 18:12:45 +0200 Subject: GetInnerRelay: update comment --- dhcpv6/dhcpv6relay.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'dhcpv6') diff --git a/dhcpv6/dhcpv6relay.go b/dhcpv6/dhcpv6relay.go index 527eddc..2387212 100644 --- a/dhcpv6/dhcpv6relay.go +++ b/dhcpv6/dhcpv6relay.go @@ -158,8 +158,8 @@ func (d *DHCPv6Relay) GetInnerMessage() (DHCPv6, error) { } } -// Recurse into a relay message and extract and return the inner DHCPv6Relay. -// Return nil if none found (e.g. not a relay message). +// GetInnerRelay recurses into a relay message and extract and return the inner +// DHCPv6Relay. Return nil if none found (e.g. not a relay message). func (r *DHCPv6Relay) GetInnerRelay() (DHCPv6, error) { p := r for { -- cgit v1.2.3 From 4fe609e1066744c0f049bdbe0c284859ee1ae230 Mon Sep 17 00:00:00 2001 From: Pablo Mazzini Date: Sat, 14 Jul 2018 01:49:02 +0200 Subject: extend DecapsulateRelay --- dhcpv6/dhcpv6.go | 35 ++++++++++++++++++++---------- dhcpv6/dhcpv6_test.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++ dhcpv6/dhcpv6relay.go | 30 ++------------------------ dhcpv6/dhcpv6relay_test.go | 25 --------------------- 4 files changed, 80 insertions(+), 64 deletions(-) (limited to 'dhcpv6') diff --git a/dhcpv6/dhcpv6.go b/dhcpv6/dhcpv6.go index d8427ea..f091897 100644 --- a/dhcpv6/dhcpv6.go +++ b/dhcpv6/dhcpv6.go @@ -1,6 +1,7 @@ package dhcpv6 import ( + "errors" "fmt" "net" ) @@ -127,22 +128,34 @@ func delOption(options []Option, code OptionCode) []Option { return newOpts } -// DecapsulateRelay extracts the content of a relay message. It does not recurse -// if there are nested relay messages. Returns the original packet if is not not -// a relay message -func DecapsulateRelay(l DHCPv6) (DHCPv6, error) { +// DecapsulateRelay extracts the content of a relay message. It takes an +// integer as index (e.g. if 0 return the outermost relay, 1 returns the +// second, etc, and -1 returns the last). Returns the original packet if +// it is not not a relay message. +func DecapsulateRelay(l DHCPv6, index int) (DHCPv6, error) { if !l.IsRelay() { return l, nil } - opt := l.GetOneOption(OPTION_RELAY_MSG) - if opt == nil { - return nil, fmt.Errorf("No OptRelayMsg found") + relay := l.(*DHCPv6Relay) + hops := int(relay.HopCount()) + if index < 0 { + index = hops + index } - relayOpt := opt.(*OptRelayMsg) - if relayOpt.RelayMessage() == nil { - return nil, fmt.Errorf("Relay message cannot be nil") + if index < 0 || index > hops { + return nil, errors.New("index out of range") } - return relayOpt.RelayMessage(), nil + for i := 0; i <= index; i++ { + opt := l.GetOneOption(OPTION_RELAY_MSG) + if opt == nil { + return nil, fmt.Errorf("No OptRelayMsg found") + } + relayOpt := opt.(*OptRelayMsg) + l = relayOpt.RelayMessage() + if l == nil { + return nil, fmt.Errorf("Relay message cannot be nil") + } + } + return l, nil } // EncapsulateRelay creates a DHCPv6Relay message containing the passed DHCPv6 diff --git a/dhcpv6/dhcpv6_test.go b/dhcpv6/dhcpv6_test.go index f8ec76d..bc56ea3 100644 --- a/dhcpv6/dhcpv6_test.go +++ b/dhcpv6/dhcpv6_test.go @@ -1,6 +1,7 @@ package dhcpv6 import ( + "net" "testing" "github.com/stretchr/testify/require" @@ -36,6 +37,59 @@ func TestNewMessage(t *testing.T) { require.Empty(t, d.(*DHCPv6Message).options) } +func TestDecapsulateRelay(t *testing.T) { + m := DHCPv6Message{} + r1, err := EncapsulateRelay(&m, RELAY_FORW, net.IPv6linklocalallnodes, net.IPv6interfacelocalallnodes) + require.NoError(t, err) + r2, err := EncapsulateRelay(r1, RELAY_FORW, net.IPv6loopback, net.IPv6linklocalallnodes) + require.NoError(t, err) + r3, err := EncapsulateRelay(r2, RELAY_FORW, net.IPv6unspecified, net.IPv6linklocalallrouters) + require.NoError(t, err) + + first, err := DecapsulateRelay(r3, 0) + require.NoError(t, err) + relay, ok := first.(*DHCPv6Relay) + require.True(t, ok) + require.Equal(t, relay.HopCount(), uint8(1)) + require.Equal(t, relay.LinkAddr(), net.IPv6loopback) + require.Equal(t, relay.PeerAddr(), net.IPv6linklocalallnodes) + + second, err := DecapsulateRelay(r3, 1) + require.NoError(t, err) + relay, ok = second.(*DHCPv6Relay) + require.True(t, ok) + require.Equal(t, relay.HopCount(), uint8(0)) + require.Equal(t, relay.LinkAddr(), net.IPv6linklocalallnodes) + require.Equal(t, relay.PeerAddr(), net.IPv6interfacelocalallnodes) + + third, err := DecapsulateRelay(r3, 2) + require.NoError(t, err) + _, ok = third.(*DHCPv6Message) + require.True(t, ok) + + _, err = DecapsulateRelay(r3, 3) + require.Error(t, err) + + rfirst, err := DecapsulateRelay(r3, -1) + require.NoError(t, err) + relay, ok = rfirst.(*DHCPv6Relay) + require.True(t, ok) + require.Equal(t, relay.HopCount(), uint8(0)) + require.Equal(t, relay.LinkAddr(), net.IPv6linklocalallnodes) + require.Equal(t, relay.PeerAddr(), net.IPv6interfacelocalallnodes) + + rsecond, err := DecapsulateRelay(r3, -2) + require.NoError(t, err) + relay, ok = rsecond.(*DHCPv6Relay) + require.True(t, ok) + require.Equal(t, relay.HopCount(), uint8(1)) + require.Equal(t, relay.LinkAddr(), net.IPv6loopback) + require.Equal(t, relay.PeerAddr(), net.IPv6linklocalallnodes) + + _, err = DecapsulateRelay(r3, -3) + require.Error(t, err) +} + func TestSettersAndGetters(t *testing.T) { d := DHCPv6Message{} // Message diff --git a/dhcpv6/dhcpv6relay.go b/dhcpv6/dhcpv6relay.go index 2387212..eaebfc2 100644 --- a/dhcpv6/dhcpv6relay.go +++ b/dhcpv6/dhcpv6relay.go @@ -151,39 +151,13 @@ func (d *DHCPv6Relay) GetInnerMessage() (DHCPv6, error) { if !p.IsRelay() { return p, nil } - p, err = DecapsulateRelay(p) + p, err = DecapsulateRelay(p, 0) if err != nil { return nil, err } } } -// GetInnerRelay recurses into a relay message and extract and return the inner -// DHCPv6Relay. Return nil if none found (e.g. not a relay message). -func (r *DHCPv6Relay) GetInnerRelay() (DHCPv6, error) { - p := r - for { - d, err := DecapsulateRelay(p) - if err != nil { - return nil, err - } - if !d.IsRelay() { - return p, nil - } - p = d.(*DHCPv6Relay) - } -} - -// GetInnerPeerAddr returns the peer address in the inner most relay info -// header, this is typically the IP address of the client making the request. -func (r *DHCPv6Relay) GetInnerPeerAddr() (net.IP, error) { - p, err := r.GetInnerRelay() - if err != nil { - return nil, err - } - return p.(*DHCPv6Relay).PeerAddr(), nil -} - // NewRelayReplFromRelayForw creates a RELAY_REPL packet based on a RELAY_FORW // packet and replaces the inner message with the passed DHCPv6 message. func NewRelayReplFromRelayForw(relayForw, msg DHCPv6) (DHCPv6, error) { @@ -212,7 +186,7 @@ func NewRelayReplFromRelayForw(relayForw, msg DHCPv6) (DHCPv6, error) { linkAddr = append(linkAddr, relay.LinkAddr()) peerAddr = append(peerAddr, relay.PeerAddr()) optiids = append(optiids, relay.GetOneOption(OPTION_INTERFACE_ID)) - decap, err := DecapsulateRelay(relay) + decap, err := DecapsulateRelay(relay, 0) if err != nil { return nil, err } diff --git a/dhcpv6/dhcpv6relay_test.go b/dhcpv6/dhcpv6relay_test.go index 3effb35..e08e6a4 100644 --- a/dhcpv6/dhcpv6relay_test.go +++ b/dhcpv6/dhcpv6relay_test.go @@ -107,31 +107,6 @@ func TestDHCPv6RelayToBytes(t *testing.T) { } } -func TestGetInnerRelay(t *testing.T) { - m := DHCPv6Message{} - r1, err := EncapsulateRelay(&m, RELAY_FORW, net.IPv6linklocalallnodes, net.IPv6interfacelocalallnodes) - require.NoError(t, err) - r2, err := EncapsulateRelay(r1, RELAY_FORW, net.IPv6loopback, net.IPv6linklocalallnodes) - require.NoError(t, err) - r3, err := EncapsulateRelay(r2, RELAY_FORW, net.IPv6unspecified, net.IPv6linklocalallrouters) - require.NoError(t, err) - - relay3, ok := r3.(*DHCPv6Relay) - require.True(t, ok) - - ir, err := relay3.GetInnerRelay() - require.NoError(t, err) - relay, ok := ir.(*DHCPv6Relay) - require.True(t, ok) - require.Equal(t, relay.HopCount(), uint8(0)) - require.Equal(t, relay.LinkAddr(), net.IPv6linklocalallnodes) - require.Equal(t, relay.PeerAddr(), net.IPv6interfacelocalallnodes) - - innerPeerAddr, err := relay3.GetInnerPeerAddr() - require.NoError(t, err) - require.Equal(t, innerPeerAddr, net.IPv6interfacelocalallnodes) -} - func TestNewRelayRepFromRelayForw(t *testing.T) { rf := DHCPv6Relay{} rf.SetMessageType(RELAY_FORW) -- cgit v1.2.3 From df4f8587f7cec8f1550c7c9a5614ce9f923ed68e Mon Sep 17 00:00:00 2001 From: Pablo Mazzini Date: Sat, 14 Jul 2018 20:18:00 +0200 Subject: add DecapsulateRelayIndex --- dhcpv6/dhcpv6.go | 53 ++++++++++++++++++++++++++++++++++----------------- dhcpv6/dhcpv6_test.go | 24 +++++------------------ 2 files changed, 40 insertions(+), 37 deletions(-) (limited to 'dhcpv6') diff --git a/dhcpv6/dhcpv6.go b/dhcpv6/dhcpv6.go index f091897..c9e42e2 100644 --- a/dhcpv6/dhcpv6.go +++ b/dhcpv6/dhcpv6.go @@ -1,7 +1,6 @@ package dhcpv6 import ( - "errors" "fmt" "net" ) @@ -128,32 +127,50 @@ func delOption(options []Option, code OptionCode) []Option { return newOpts } -// DecapsulateRelay extracts the content of a relay message. It takes an +// DecapsulateRelay extracts the content of a relay message. It does not recurse +// if there are nested relay messages. Returns the original packet if is not not +// a relay message +func DecapsulateRelay(l DHCPv6) (DHCPv6, error) { + if !l.IsRelay() { + return l, nil + } + opt := l.GetOneOption(OPTION_RELAY_MSG) + if opt == nil { + return nil, fmt.Errorf("No OptRelayMsg found") + } + relayOpt := opt.(*OptRelayMsg) + if relayOpt.RelayMessage() == nil { + return nil, fmt.Errorf("Relay message cannot be nil") + } + return relayOpt.RelayMessage(), nil +} + +// DecapsulateRelayIndex extracts the content of a relay message. It takes an // integer as index (e.g. if 0 return the outermost relay, 1 returns the // second, etc, and -1 returns the last). Returns the original packet if // it is not not a relay message. -func DecapsulateRelay(l DHCPv6, index int) (DHCPv6, error) { +func DecapsulateRelayIndex(l DHCPv6, index int) (DHCPv6, error) { if !l.IsRelay() { return l, nil } - relay := l.(*DHCPv6Relay) - hops := int(relay.HopCount()) - if index < 0 { - index = hops + index - } - if index < 0 || index > hops { - return nil, errors.New("index out of range") + if index == -1 { + for { + d, err := DecapsulateRelay(l) + if err != nil { + return nil, err + } + if !d.IsRelay() { + return l, nil + } + l = d + } } for i := 0; i <= index; i++ { - opt := l.GetOneOption(OPTION_RELAY_MSG) - if opt == nil { - return nil, fmt.Errorf("No OptRelayMsg found") - } - relayOpt := opt.(*OptRelayMsg) - l = relayOpt.RelayMessage() - if l == nil { - return nil, fmt.Errorf("Relay message cannot be nil") + d, err := DecapsulateRelay(l) + if err != nil { + return nil, err } + l = d } return l, nil } diff --git a/dhcpv6/dhcpv6_test.go b/dhcpv6/dhcpv6_test.go index bc56ea3..6b7d2df 100644 --- a/dhcpv6/dhcpv6_test.go +++ b/dhcpv6/dhcpv6_test.go @@ -37,7 +37,7 @@ func TestNewMessage(t *testing.T) { require.Empty(t, d.(*DHCPv6Message).options) } -func TestDecapsulateRelay(t *testing.T) { +func TestDecapsulateRelayIndex(t *testing.T) { m := DHCPv6Message{} r1, err := EncapsulateRelay(&m, RELAY_FORW, net.IPv6linklocalallnodes, net.IPv6interfacelocalallnodes) require.NoError(t, err) @@ -46,7 +46,7 @@ func TestDecapsulateRelay(t *testing.T) { r3, err := EncapsulateRelay(r2, RELAY_FORW, net.IPv6unspecified, net.IPv6linklocalallrouters) require.NoError(t, err) - first, err := DecapsulateRelay(r3, 0) + first, err := DecapsulateRelayIndex(r3, 0) require.NoError(t, err) relay, ok := first.(*DHCPv6Relay) require.True(t, ok) @@ -54,7 +54,7 @@ func TestDecapsulateRelay(t *testing.T) { require.Equal(t, relay.LinkAddr(), net.IPv6loopback) require.Equal(t, relay.PeerAddr(), net.IPv6linklocalallnodes) - second, err := DecapsulateRelay(r3, 1) + second, err := DecapsulateRelayIndex(r3, 1) require.NoError(t, err) relay, ok = second.(*DHCPv6Relay) require.True(t, ok) @@ -62,32 +62,18 @@ func TestDecapsulateRelay(t *testing.T) { require.Equal(t, relay.LinkAddr(), net.IPv6linklocalallnodes) require.Equal(t, relay.PeerAddr(), net.IPv6interfacelocalallnodes) - third, err := DecapsulateRelay(r3, 2) + third, err := DecapsulateRelayIndex(r3, 2) require.NoError(t, err) _, ok = third.(*DHCPv6Message) require.True(t, ok) - _, err = DecapsulateRelay(r3, 3) - require.Error(t, err) - - rfirst, err := DecapsulateRelay(r3, -1) + rfirst, err := DecapsulateRelayIndex(r3, -1) require.NoError(t, err) relay, ok = rfirst.(*DHCPv6Relay) require.True(t, ok) require.Equal(t, relay.HopCount(), uint8(0)) require.Equal(t, relay.LinkAddr(), net.IPv6linklocalallnodes) require.Equal(t, relay.PeerAddr(), net.IPv6interfacelocalallnodes) - - rsecond, err := DecapsulateRelay(r3, -2) - require.NoError(t, err) - relay, ok = rsecond.(*DHCPv6Relay) - require.True(t, ok) - require.Equal(t, relay.HopCount(), uint8(1)) - require.Equal(t, relay.LinkAddr(), net.IPv6loopback) - require.Equal(t, relay.PeerAddr(), net.IPv6linklocalallnodes) - - _, err = DecapsulateRelay(r3, -3) - require.Error(t, err) } func TestSettersAndGetters(t *testing.T) { -- cgit v1.2.3 From 2ae16808e62447f746632531328742403c487b36 Mon Sep 17 00:00:00 2001 From: Pablo Mazzini Date: Sat, 14 Jul 2018 20:20:55 +0200 Subject: add missing file --- dhcpv6/dhcpv6relay.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'dhcpv6') diff --git a/dhcpv6/dhcpv6relay.go b/dhcpv6/dhcpv6relay.go index eaebfc2..38f2994 100644 --- a/dhcpv6/dhcpv6relay.go +++ b/dhcpv6/dhcpv6relay.go @@ -151,7 +151,7 @@ func (d *DHCPv6Relay) GetInnerMessage() (DHCPv6, error) { if !p.IsRelay() { return p, nil } - p, err = DecapsulateRelay(p, 0) + p, err = DecapsulateRelay(p) if err != nil { return nil, err } @@ -186,7 +186,7 @@ func NewRelayReplFromRelayForw(relayForw, msg DHCPv6) (DHCPv6, error) { linkAddr = append(linkAddr, relay.LinkAddr()) peerAddr = append(peerAddr, relay.PeerAddr()) optiids = append(optiids, relay.GetOneOption(OPTION_INTERFACE_ID)) - decap, err := DecapsulateRelay(relay, 0) + decap, err := DecapsulateRelay(relay) if err != nil { return nil, err } -- cgit v1.2.3 From ae64b38d35aaa4ff0cc58ab617b0cb367389fb5d Mon Sep 17 00:00:00 2001 From: Pablo Mazzini Date: Sat, 14 Jul 2018 20:31:12 +0200 Subject: return error if index < -1 --- dhcpv6/dhcpv6.go | 4 +++- dhcpv6/dhcpv6_test.go | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'dhcpv6') diff --git a/dhcpv6/dhcpv6.go b/dhcpv6/dhcpv6.go index c9e42e2..b424101 100644 --- a/dhcpv6/dhcpv6.go +++ b/dhcpv6/dhcpv6.go @@ -153,7 +153,9 @@ func DecapsulateRelayIndex(l DHCPv6, index int) (DHCPv6, error) { if !l.IsRelay() { return l, nil } - if index == -1 { + if index < -1 { + return nil, fmt.Errorf("Invalid index: %d", index) + } else if index == -1 { for { d, err := DecapsulateRelay(l) if err != nil { diff --git a/dhcpv6/dhcpv6_test.go b/dhcpv6/dhcpv6_test.go index 6b7d2df..2db5649 100644 --- a/dhcpv6/dhcpv6_test.go +++ b/dhcpv6/dhcpv6_test.go @@ -74,6 +74,9 @@ func TestDecapsulateRelayIndex(t *testing.T) { require.Equal(t, relay.HopCount(), uint8(0)) require.Equal(t, relay.LinkAddr(), net.IPv6linklocalallnodes) require.Equal(t, relay.PeerAddr(), net.IPv6interfacelocalallnodes) + + _, err = DecapsulateRelayIndex(r3, -2) + require.Error(t, err) } func TestSettersAndGetters(t *testing.T) { -- cgit v1.2.3