Permalink
Browse files

New packet6.GetInnerMostPeerAddr to extract mac address from the inne…

…rmost peer-address field of the relay message option.

Summary:
When you have multiple relay relaying messages you are going to end up with multiple relay message payloads stacked one on top of the other. this diff adds a new public function called GetInnerMostPeerAddr which provides the peer address fields of the relay information closest to the DHCP Client, that typically is set to the EUI-64 IPv6 address by the cloest relay to the client.
We currently use that to infer the mac address for a client, even if the client doesn't use DUID-LL[T].

Reviewed By: rb2k, malmond77, nemith

Differential Revision: D5592407

fbshipit-source-id: 92a1079cd3b49290c0921746b789f092b0934626
  • Loading branch information...
pallotron authored and facebook-github-bot committed Aug 9, 2017
1 parent 7f3b385 commit 91e9af5a72d4322ea6f9ad222418867536c2efe3
Showing with 82 additions and 3 deletions.
  1. +25 −3 lib/packet6.go
  2. +57 −0 lib/packet6_test.go
View
@@ -146,7 +146,8 @@ func (p Packet6) XID() (uint32, error) {
// Hops returns the number of hops for a Packet6
func (p Packet6) Hops() (byte, error) {
if t, err := p.Type(); err != nil || (t != RelayForw && t != RelayRepl) {
return 0, errors.New("Not a RelayForw or RelayRepl, does not have hopcount")
return 0, errors.New(
"Not a RelayForw or RelayRepl, does not have hop count")
}
return p[1], nil
}
@@ -199,6 +200,26 @@ func (p Packet6) DuidTypeName() (string, error) {
}
}
// GetInnerMostPeerAddress returns the peer address in the inner most relay info
// header, this is typically the mac address of the relay closer to the dhcp
// client making the request.
func (p Packet6) GetInnerMostPeerAddr() (net.IP, error) {
packet := Packet6(make([]byte, len(p)))
copy(packet, p)
hops, err := packet.Hops()
var addr net.IP
if err != nil {
return nil, err
}
for i := 0; i <= int(hops); i++ {
packet, addr, err = packet.Unwind()
if err != nil {
return nil, err
}
}
return addr, nil
}
// Mac returns the Mac addressed embededded in the DUID, note that this only
// works with type DuidLL and DuidLLT. If the request is not using DUID-LL[T]
// then we look into the PeerAddr field in the RelayInfo header.
@@ -212,8 +233,9 @@ func (p Packet6) Mac() ([]byte, error) {
}
duidType := DuidType(binary.BigEndian.Uint16(duid[0:2]))
if duidType != DuidLLT && duidType != DuidLL {
// look at PeerAddress if there
ip, err := p.PeerAddr()
// look at inner most peer address, which is set by the closest relay
// to the dhcp client
ip, err := p.GetInnerMostPeerAddr()
if err != nil {
return nil, err
} else {
View
@@ -250,3 +250,60 @@ func TestMalformedPacket(t *testing.T) {
t.Fatalf("Should be unable to extract dhcp6message, but did not fail")
}
}
func TestStackedRelayInfo(t *testing.T) {
// taken from a production tcpdump
bytes := []byte{
0x0c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x24, 0x01, 0xdb, 0x00, 0x01, 0x11,
0x70, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0a, 0x00, 0x09, 0x00, 0x60, 0x0c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x26, 0x8a, 0x07, 0xff, 0xfe, 0x87, 0xf9, 0x7f,
0x00, 0x12, 0x00, 0x06, 0x24, 0x8a, 0x07, 0x87,
0xf9, 0x7f, 0x00, 0x09, 0x00, 0x30, 0x01, 0x50,
0xb4, 0x93, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x03,
0x00, 0x01, 0x24, 0x8a, 0x07, 0x87, 0xf9, 0x7f,
0x00, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x2b, 0x67,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x00, 0x02, 0xff, 0xff, 0x00, 0x06,
0x00, 0x04, 0x00, 0x17, 0x00, 0x18,
}
packet := Packet6(bytes)
msg, err := packet.dhcp6message()
if err != nil {
t.Fatalf("Failed to extract message")
}
// type should be SOLICIT
msgType, _ := msg.Type()
if msgType != Solicit {
t.Fatalf("Expected type %s but got %s", Solicit, msgType)
}
// XID should be 0x00cd2e
xid, err := msg.XID()
if err != nil {
t.Fatalf("Failed to extract XId: %s", err)
}
if xid != 0x50b493 {
t.Fatalf("Expected xid 0x%x but got 0x%x", 0x50b493, xid)
}
// Hops should be 2
hops, err := packet.Hops()
if err != nil {
t.Fatalf("Failed to extract XId: %s", err)
}
if hops != 1 {
t.Fatalf("Expected 1 hop, got %d", hops)
}
addr, err := packet.GetInnerMostPeerAddr()
if err != nil {
t.Fatalf("Failed running GetInnerMostPeerAddr: %s", err)
}
if addr.String() != "fe80::268a:7ff:fe87:f97f" {
t.Fatalf(
"Expected %s but got %s", "fe80::268a:7ff:fe87:f97f", addr.String())
}
}

0 comments on commit 91e9af5

Please sign in to comment.