Add a type to represent the NDP Router Advertisement message.

This change is in preparation for NDP Router Discovery where the stack will need
to handle NDP Router Advertisments.

Tests: Test that given an NDP Router Advertisement buffer (body of an ICMPv6
packet, correct values are returned by the field getters).
PiperOrigin-RevId: 276146817
This commit is contained in:
Ghanan Gowripalan
2019-10-22 14:41:51 -07:00
committed by gVisor bot
parent c356fe2ebb
commit 515e0558d4
5 changed files with 152 additions and 0 deletions
+1
View File
@@ -19,6 +19,7 @@ go_library(
"ndp_neighbor_advert.go",
"ndp_neighbor_solicit.go",
"ndp_options.go",
"ndp_router_advert.go",
"tcp.go",
"udp.go",
],
+2
View File
@@ -18,6 +18,8 @@ import "gvisor.dev/gvisor/pkg/tcpip"
// NDPNeighborAdvert is an NDP Neighbor Advertisement message. It will
// only contain the body of an ICMPv6 packet.
//
// See RFC 4861 section 4.4 for more details.
type NDPNeighborAdvert []byte
const (
+2
View File
@@ -18,6 +18,8 @@ import "gvisor.dev/gvisor/pkg/tcpip"
// NDPNeighborSolicit is an NDP Neighbor Solicitation message. It will only
// contain the body of an ICMPv6 packet.
//
// See RFC 4861 section 4.3 for more details.
type NDPNeighborSolicit []byte
const (
+112
View File
@@ -0,0 +1,112 @@
// 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
import (
"encoding/binary"
"time"
)
// NDPRouterAdvert is an NDP Router Advertisement message. It will only contain
// the body of an ICMPv6 packet.
//
// See RFC 4861 section 4.2 for more details.
type NDPRouterAdvert []byte
const (
// NDPRAMinimumSize is the minimum size of a valid NDP Router
// Advertisement message (body of an ICMPv6 packet).
NDPRAMinimumSize = 12
// ndpRACurrHopLimitOffset is the byte of the Curr Hop Limit field
// within an NDPRouterAdvert.
ndpRACurrHopLimitOffset = 0
// ndpRAFlagsOffset is the byte with the NDP RA bit-fields/flags
// within an NDPRouterAdvert.
ndpRAFlagsOffset = 1
// ndpRAManagedAddrConfFlagMask is the mask of the Managed Address
// Configuration flag within the bit-field/flags byte of an
// NDPRouterAdvert.
ndpRAManagedAddrConfFlagMask = (1 << 7)
// ndpRAOtherConfFlagMask is the mask of the Other Configuration flag
// within the bit-field/flags byte of an NDPRouterAdvert.
ndpRAOtherConfFlagMask = (1 << 6)
// ndpRARouterLifetimeOffset is the start of the 2-byte Router Lifetime
// field within an NDPRouterAdvert.
ndpRARouterLifetimeOffset = 2
// ndpRAReachableTimeOffset is the start of the 4-byte Reachable Time
// field within an NDPRouterAdvert.
ndpRAReachableTimeOffset = 4
// ndpRARetransTimerOffset is the start of the 4-byte Retrans Timer
// field within an NDPRouterAdvert.
ndpRARetransTimerOffset = 8
// ndpRAOptionsOffset is the start of the NDP options in an
// NDPRouterAdvert.
ndpRAOptionsOffset = 12
)
// CurrHopLimit returns the value of the Curr Hop Limit field.
func (b NDPRouterAdvert) CurrHopLimit() uint8 {
return b[ndpRACurrHopLimitOffset]
}
// ManagedAddrConfFlag returns the value of the Managed Address Configuration
// flag.
func (b NDPRouterAdvert) ManagedAddrConfFlag() bool {
return b[ndpRAFlagsOffset]&ndpRAManagedAddrConfFlagMask != 0
}
// OtherConfFlag returns the value of the Other Configuration flag.
func (b NDPRouterAdvert) OtherConfFlag() bool {
return b[ndpRAFlagsOffset]&ndpRAOtherConfFlagMask != 0
}
// RouterLifetime returns the lifetime associated with the default router. A
// value of 0 means the source of the Router Advertisement is not a default
// router and SHOULD NOT appear on the default router list. Note, a value of 0
// only means that the router should not be used as a default router, it does
// not apply to other information contained in the Router Advertisement.
func (b NDPRouterAdvert) RouterLifetime() time.Duration {
// The field is the time in seconds, as per RFC 4861 section 4.2.
return time.Second * time.Duration(binary.BigEndian.Uint16(b[ndpRARouterLifetimeOffset:]))
}
// ReachableTime returns the time that a node assumes a neighbor is reachable
// after having received a reachability confirmation. A value of 0 means
// that it is unspecified by the source of the Router Advertisement message.
func (b NDPRouterAdvert) ReachableTime() time.Duration {
// The field is the time in milliseconds, as per RFC 4861 section 4.2.
return time.Millisecond * time.Duration(binary.BigEndian.Uint32(b[ndpRAReachableTimeOffset:]))
}
// RetransTimer returns the time between retransmitted Neighbor Solicitation
// messages. A value of 0 means that it is unspecified by the source of the
// Router Advertisement message.
func (b NDPRouterAdvert) RetransTimer() time.Duration {
// The field is the time in milliseconds, as per RFC 4861 section 4.2.
return time.Millisecond * time.Duration(binary.BigEndian.Uint32(b[ndpRARetransTimerOffset:]))
}
// Options returns an NDPOptions of the the options body.
func (b NDPRouterAdvert) Options() NDPOptions {
return NDPOptions(b[ndpRAOptionsOffset:])
}
+35
View File
@@ -17,6 +17,7 @@ package header
import (
"bytes"
"testing"
"time"
"gvisor.dev/gvisor/pkg/tcpip"
)
@@ -117,6 +118,40 @@ func TestNDPNeighborAdvert(t *testing.T) {
}
}
func TestNDPRouterAdvert(t *testing.T) {
b := []byte{
64, 128, 1, 2,
3, 4, 5, 6,
7, 8, 9, 10,
}
ra := NDPRouterAdvert(b)
if got := ra.CurrHopLimit(); got != 64 {
t.Fatalf("got ra.CurrHopLimit = %d, want = 64", got)
}
if got := ra.ManagedAddrConfFlag(); !got {
t.Fatalf("got ManagedAddrConfFlag = false, want = true")
}
if got := ra.OtherConfFlag(); got {
t.Fatalf("got OtherConfFlag = true, want = false")
}
if got, want := ra.RouterLifetime(), time.Second*258; got != want {
t.Fatalf("got ra.RouterLifetime = %d, want = %d", got, want)
}
if got, want := ra.ReachableTime(), time.Millisecond*50595078; got != want {
t.Fatalf("got ra.ReachableTime = %d, want = %d", got, want)
}
if got, want := ra.RetransTimer(), time.Millisecond*117967114; got != want {
t.Fatalf("got ra.RetransTimer = %d, want = %d", got, want)
}
}
// TestNDPTargetLinkLayerAddressOptionSerialize tests serializing a
// NDPTargetLinkLayerAddressOption.
func TestNDPTargetLinkLayerAddressOptionSerialize(t *testing.T) {