From ad80dcf47077a1938631fe36f6b406256f3f3f4f Mon Sep 17 00:00:00 2001 From: Ghanan Gowripalan Date: Fri, 13 Dec 2019 16:26:06 -0800 Subject: Properly generate the EUI64 interface identifier from an Ethernet address Fixed a bug where the interface identifier was not properly generated from an Ethernet address. Tests: Unittests to make sure the functions generating the EUI64 interface identifier are correct. PiperOrigin-RevId: 285494562 --- pkg/tcpip/header/BUILD | 3 +++ pkg/tcpip/header/ipv6.go | 21 ++++++++++---------- pkg/tcpip/header/ipv6_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++ pkg/tcpip/stack/ndp.go | 6 +++--- pkg/tcpip/stack/ndp_test.go | 2 +- 5 files changed, 63 insertions(+), 14 deletions(-) create mode 100644 pkg/tcpip/header/ipv6_test.go diff --git a/pkg/tcpip/header/BUILD b/pkg/tcpip/header/BUILD index 8392cb9e5..f1d837196 100644 --- a/pkg/tcpip/header/BUILD +++ b/pkg/tcpip/header/BUILD @@ -38,12 +38,15 @@ go_test( size = "small", srcs = [ "checksum_test.go", + "ipv6_test.go", "ipversion_test.go", "tcp_test.go", ], deps = [ ":header", + "//pkg/tcpip", "//pkg/tcpip/buffer", + "@com_github_google_go-cmp//cmp:go_default_library", ], ) diff --git a/pkg/tcpip/header/ipv6.go b/pkg/tcpip/header/ipv6.go index 5275b34d4..fc671e439 100644 --- a/pkg/tcpip/header/ipv6.go +++ b/pkg/tcpip/header/ipv6.go @@ -278,33 +278,34 @@ func SolicitedNodeAddr(addr tcpip.Address) tcpip.Address { return solicitedNodeMulticastPrefix + addr[len(addr)-3:] } -// EthernetAdddressToEUI64IntoBuf populates buf with a EUI-64 from a 48-bit -// Ethernet/MAC address. +// EthernetAdddressToModifiedEUI64IntoBuf populates buf with a modified EUI-64 +// from a 48-bit Ethernet/MAC address, as per RFC 4291 section 2.5.1. // // buf MUST be at least 8 bytes. -func EthernetAdddressToEUI64IntoBuf(linkAddr tcpip.LinkAddress, buf []byte) { +func EthernetAdddressToModifiedEUI64IntoBuf(linkAddr tcpip.LinkAddress, buf []byte) { buf[0] = linkAddr[0] ^ 2 buf[1] = linkAddr[1] buf[2] = linkAddr[2] - buf[3] = 0xFE + buf[3] = 0xFF buf[4] = 0xFE buf[5] = linkAddr[3] buf[6] = linkAddr[4] buf[7] = linkAddr[5] } -// EthernetAddressToEUI64 computes an EUI-64 from a 48-bit Ethernet/MAC address. -func EthernetAddressToEUI64(linkAddr tcpip.LinkAddress) [IIDSize]byte { +// EthernetAddressToModifiedEUI64 computes a modified EUI-64 from a 48-bit +// Ethernet/MAC address, as per RFC 4291 section 2.5.1. +func EthernetAddressToModifiedEUI64(linkAddr tcpip.LinkAddress) [IIDSize]byte { var buf [IIDSize]byte - EthernetAdddressToEUI64IntoBuf(linkAddr, buf[:]) + EthernetAdddressToModifiedEUI64IntoBuf(linkAddr, buf[:]) return buf } // LinkLocalAddr computes the default IPv6 link-local address from a link-layer // (MAC) address. func LinkLocalAddr(linkAddr tcpip.LinkAddress) tcpip.Address { - // Convert a 48-bit MAC to an EUI-64 and then prepend the link-local - // header, FE80::. + // Convert a 48-bit MAC to a modified EUI-64 and then prepend the + // link-local header, FE80::. // // The conversion is very nearly: // aa:bb:cc:dd:ee:ff => FE80::Aabb:ccFF:FEdd:eeff @@ -313,7 +314,7 @@ func LinkLocalAddr(linkAddr tcpip.LinkAddress) tcpip.Address { 0: 0xFE, 1: 0x80, } - EthernetAdddressToEUI64IntoBuf(linkAddr, lladdrb[IIDOffsetInIPv6Address:]) + EthernetAdddressToModifiedEUI64IntoBuf(linkAddr, lladdrb[IIDOffsetInIPv6Address:]) return tcpip.Address(lladdrb[:]) } diff --git a/pkg/tcpip/header/ipv6_test.go b/pkg/tcpip/header/ipv6_test.go new file mode 100644 index 000000000..42c5c6fc1 --- /dev/null +++ b/pkg/tcpip/header/ipv6_test.go @@ -0,0 +1,45 @@ +// Copyright 2019 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package header_test + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "gvisor.dev/gvisor/pkg/tcpip" + "gvisor.dev/gvisor/pkg/tcpip/header" +) + +const linkAddr = tcpip.LinkAddress("\x02\x02\x03\x04\x05\x06") + +func TestEthernetAdddressToModifiedEUI64(t *testing.T) { + expectedIID := [header.IIDSize]byte{0, 2, 3, 255, 254, 4, 5, 6} + + if diff := cmp.Diff(expectedIID, header.EthernetAddressToModifiedEUI64(linkAddr)); diff != "" { + t.Errorf("EthernetAddressToModifiedEUI64(%s) mismatch (-want +got):\n%s", linkAddr, diff) + } + + var buf [header.IIDSize]byte + header.EthernetAdddressToModifiedEUI64IntoBuf(linkAddr, buf[:]) + if diff := cmp.Diff(expectedIID, buf); diff != "" { + t.Errorf("EthernetAddressToModifiedEUI64IntoBuf(%s, _) mismatch (-want +got):\n%s", linkAddr, diff) + } +} + +func TestLinkLocalAddr(t *testing.T) { + if got, want := header.LinkLocalAddr(linkAddr), tcpip.Address("\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x02\x03\xff\xfe\x04\x05\x06"); got != want { + t.Errorf("got LinkLocalAddr(%s) = %s, want = %s", linkAddr, got, want) + } +} diff --git a/pkg/tcpip/stack/ndp.go b/pkg/tcpip/stack/ndp.go index 060a2e7c6..27bd02e76 100644 --- a/pkg/tcpip/stack/ndp.go +++ b/pkg/tcpip/stack/ndp.go @@ -1049,11 +1049,11 @@ func (ndp *ndpState) handleAutonomousPrefixInformation(pi header.NDPPrefixInform return } - // Generate an address within prefix from the EUI-64 of ndp's NIC's - // Ethernet MAC address. + // Generate an address within prefix from the modified EUI-64 of ndp's + // NIC's Ethernet MAC address. addrBytes := make([]byte, header.IPv6AddressSize) copy(addrBytes[:header.IIDOffsetInIPv6Address], prefix.ID()[:header.IIDOffsetInIPv6Address]) - header.EthernetAdddressToEUI64IntoBuf(linkAddr, addrBytes[header.IIDOffsetInIPv6Address:]) + header.EthernetAdddressToModifiedEUI64IntoBuf(linkAddr, addrBytes[header.IIDOffsetInIPv6Address:]) addr := tcpip.Address(addrBytes) addrWithPrefix := tcpip.AddressWithPrefix{ Address: addr, diff --git a/pkg/tcpip/stack/ndp_test.go b/pkg/tcpip/stack/ndp_test.go index 8d811eb8e..d8e7ce67e 100644 --- a/pkg/tcpip/stack/ndp_test.go +++ b/pkg/tcpip/stack/ndp_test.go @@ -62,7 +62,7 @@ func prefixSubnetAddr(offset uint8, linkAddr tcpip.LinkAddress) (tcpip.AddressWi var addr tcpip.AddressWithPrefix if header.IsValidUnicastEthernetAddress(linkAddr) { addrBytes := []byte(subnet.ID()) - header.EthernetAdddressToEUI64IntoBuf(linkAddr, addrBytes[header.IIDOffsetInIPv6Address:]) + header.EthernetAdddressToModifiedEUI64IntoBuf(linkAddr, addrBytes[header.IIDOffsetInIPv6Address:]) addr = tcpip.AddressWithPrefix{ Address: tcpip.Address(addrBytes), PrefixLen: 64, -- cgit v1.2.3