| // 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:]) |
| } |