mirror of
https://github.com/SagerNet/sing-tun.git
synced 2025-04-02 19:37:40 +03:00
204 lines
7.3 KiB
Go
204 lines
7.3 KiB
Go
// 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"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
var _ fmt.Stringer = NDPRoutePreference(0)
|
|
|
|
// NDPRoutePreference is the preference values for default routers or
|
|
// more-specific routes.
|
|
//
|
|
// As per RFC 4191 section 2.1,
|
|
//
|
|
// Default router preferences and preferences for more-specific routes
|
|
// are encoded the same way.
|
|
//
|
|
// Preference values are encoded as a two-bit signed integer, as
|
|
// follows:
|
|
//
|
|
// 01 High
|
|
// 00 Medium (default)
|
|
// 11 Low
|
|
// 10 Reserved - MUST NOT be sent
|
|
//
|
|
// Note that implementations can treat the value as a two-bit signed
|
|
// integer.
|
|
//
|
|
// Having just three values reinforces that they are not metrics and
|
|
// more values do not appear to be necessary for reasonable scenarios.
|
|
type NDPRoutePreference uint8
|
|
|
|
const (
|
|
// HighRoutePreference indicates a high preference, as per
|
|
// RFC 4191 section 2.1.
|
|
HighRoutePreference NDPRoutePreference = 0b01
|
|
|
|
// MediumRoutePreference indicates a medium preference, as per
|
|
// RFC 4191 section 2.1.
|
|
//
|
|
// This is the default preference value.
|
|
MediumRoutePreference = 0b00
|
|
|
|
// LowRoutePreference indicates a low preference, as per
|
|
// RFC 4191 section 2.1.
|
|
LowRoutePreference = 0b11
|
|
|
|
// ReservedRoutePreference is a reserved preference value, as per
|
|
// RFC 4191 section 2.1.
|
|
//
|
|
// It MUST NOT be sent.
|
|
ReservedRoutePreference = 0b10
|
|
)
|
|
|
|
// String implements fmt.Stringer.
|
|
func (p NDPRoutePreference) String() string {
|
|
switch p {
|
|
case HighRoutePreference:
|
|
return "HighRoutePreference"
|
|
case MediumRoutePreference:
|
|
return "MediumRoutePreference"
|
|
case LowRoutePreference:
|
|
return "LowRoutePreference"
|
|
case ReservedRoutePreference:
|
|
return "ReservedRoutePreference"
|
|
default:
|
|
return fmt.Sprintf("NDPRoutePreference(%d)", p)
|
|
}
|
|
}
|
|
|
|
// NDPRouterAdvert is an NDP Router Advertisement message. It will only contain
|
|
// the body of an ICMPv6 packet.
|
|
//
|
|
// See RFC 4861 section 4.2 and RFC 4191 section 2.2 for more details.
|
|
type NDPRouterAdvert []byte
|
|
|
|
// As per RFC 4191 section 2.2,
|
|
//
|
|
// 0 1 2 3
|
|
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | Type | Code | Checksum |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | Cur Hop Limit |M|O|H|Prf|Resvd| Router Lifetime |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | Reachable Time |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | Retrans Timer |
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
// | Options ...
|
|
// +-+-+-+-+-+-+-+-+-+-+-+-
|
|
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)
|
|
|
|
// ndpDefaultRouterPreferenceShift is the shift of the Prf (Default Router
|
|
// Preference) field within the flags byte of an NDPRouterAdvert.
|
|
ndpDefaultRouterPreferenceShift = 3
|
|
|
|
// ndpDefaultRouterPreferenceMask is the mask of the Prf (Default Router
|
|
// Preference) field within the flags byte of an NDPRouterAdvert.
|
|
ndpDefaultRouterPreferenceMask = (0b11 << ndpDefaultRouterPreferenceShift)
|
|
|
|
// 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
|
|
}
|
|
|
|
// DefaultRouterPreference returns the Default Router Preference field.
|
|
func (b NDPRouterAdvert) DefaultRouterPreference() NDPRoutePreference {
|
|
return NDPRoutePreference((b[ndpRAFlagsOffset] & ndpDefaultRouterPreferenceMask) >> ndpDefaultRouterPreferenceShift)
|
|
}
|
|
|
|
// 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 options body.
|
|
func (b NDPRouterAdvert) Options() NDPOptions {
|
|
return NDPOptions(b[ndpRAOptionsOffset:])
|
|
}
|