// 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 the options body. func (b NDPRouterAdvert) Options() NDPOptions { return NDPOptions(b[ndpRAOptionsOffset:]) }