github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/pkg/tcpip/header/ndp_router_advert.go (about)

     1  // Copyright 2019 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package header
    16  
    17  import (
    18  	"encoding/binary"
    19  	"fmt"
    20  	"time"
    21  )
    22  
    23  var _ fmt.Stringer = NDPRoutePreference(0)
    24  
    25  // NDPRoutePreference is the preference values for default routers or
    26  // more-specific routes.
    27  //
    28  // As per RFC 4191 section 2.1,
    29  //
    30  //	Default router preferences and preferences for more-specific routes
    31  //	are encoded the same way.
    32  //
    33  //	Preference values are encoded as a two-bit signed integer, as
    34  //	follows:
    35  //
    36  //	   01      High
    37  //	   00      Medium (default)
    38  //	   11      Low
    39  //	   10      Reserved - MUST NOT be sent
    40  //
    41  //	Note that implementations can treat the value as a two-bit signed
    42  //	integer.
    43  //
    44  //	Having just three values reinforces that they are not metrics and
    45  //	more values do not appear to be necessary for reasonable scenarios.
    46  type NDPRoutePreference uint8
    47  
    48  const (
    49  	// HighRoutePreference indicates a high preference, as per
    50  	// RFC 4191 section 2.1.
    51  	HighRoutePreference NDPRoutePreference = 0b01
    52  
    53  	// MediumRoutePreference indicates a medium preference, as per
    54  	// RFC 4191 section 2.1.
    55  	//
    56  	// This is the default preference value.
    57  	MediumRoutePreference = 0b00
    58  
    59  	// LowRoutePreference indicates a low preference, as per
    60  	// RFC 4191 section 2.1.
    61  	LowRoutePreference = 0b11
    62  
    63  	// ReservedRoutePreference is a reserved preference value, as per
    64  	// RFC 4191 section 2.1.
    65  	//
    66  	// It MUST NOT be sent.
    67  	ReservedRoutePreference = 0b10
    68  )
    69  
    70  // String implements fmt.Stringer.
    71  func (p NDPRoutePreference) String() string {
    72  	switch p {
    73  	case HighRoutePreference:
    74  		return "HighRoutePreference"
    75  	case MediumRoutePreference:
    76  		return "MediumRoutePreference"
    77  	case LowRoutePreference:
    78  		return "LowRoutePreference"
    79  	case ReservedRoutePreference:
    80  		return "ReservedRoutePreference"
    81  	default:
    82  		return fmt.Sprintf("NDPRoutePreference(%d)", p)
    83  	}
    84  }
    85  
    86  // NDPRouterAdvert is an NDP Router Advertisement message. It will only contain
    87  // the body of an ICMPv6 packet.
    88  //
    89  // See RFC 4861 section 4.2 and RFC 4191 section 2.2 for more details.
    90  type NDPRouterAdvert []byte
    91  
    92  // As per RFC 4191 section 2.2,
    93  //
    94  //	 0                   1                   2                   3
    95  //	 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
    96  //	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    97  //	|     Type      |     Code      |          Checksum             |
    98  //	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    99  //	| Cur Hop Limit |M|O|H|Prf|Resvd|       Router Lifetime         |
   100  //	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   101  //	|                         Reachable Time                        |
   102  //	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   103  //	|                          Retrans Timer                        |
   104  //	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   105  //	|   Options ...
   106  //	+-+-+-+-+-+-+-+-+-+-+-+-
   107  const (
   108  	// NDPRAMinimumSize is the minimum size of a valid NDP Router
   109  	// Advertisement message (body of an ICMPv6 packet).
   110  	NDPRAMinimumSize = 12
   111  
   112  	// ndpRACurrHopLimitOffset is the byte of the Curr Hop Limit field
   113  	// within an NDPRouterAdvert.
   114  	ndpRACurrHopLimitOffset = 0
   115  
   116  	// ndpRAFlagsOffset is the byte with the NDP RA bit-fields/flags
   117  	// within an NDPRouterAdvert.
   118  	ndpRAFlagsOffset = 1
   119  
   120  	// ndpRAManagedAddrConfFlagMask is the mask of the Managed Address
   121  	// Configuration flag within the bit-field/flags byte of an
   122  	// NDPRouterAdvert.
   123  	ndpRAManagedAddrConfFlagMask = (1 << 7)
   124  
   125  	// ndpRAOtherConfFlagMask is the mask of the Other Configuration flag
   126  	// within the bit-field/flags byte of an NDPRouterAdvert.
   127  	ndpRAOtherConfFlagMask = (1 << 6)
   128  
   129  	// ndpDefaultRouterPreferenceShift is the shift of the Prf (Default Router
   130  	// Preference) field within the flags byte of an NDPRouterAdvert.
   131  	ndpDefaultRouterPreferenceShift = 3
   132  
   133  	// ndpDefaultRouterPreferenceMask is the mask of the Prf (Default Router
   134  	// Preference) field within the flags byte of an NDPRouterAdvert.
   135  	ndpDefaultRouterPreferenceMask = (0b11 << ndpDefaultRouterPreferenceShift)
   136  
   137  	// ndpRARouterLifetimeOffset is the start of the 2-byte Router Lifetime
   138  	// field within an NDPRouterAdvert.
   139  	ndpRARouterLifetimeOffset = 2
   140  
   141  	// ndpRAReachableTimeOffset is the start of the 4-byte Reachable Time
   142  	// field within an NDPRouterAdvert.
   143  	ndpRAReachableTimeOffset = 4
   144  
   145  	// ndpRARetransTimerOffset is the start of the 4-byte Retrans Timer
   146  	// field within an NDPRouterAdvert.
   147  	ndpRARetransTimerOffset = 8
   148  
   149  	// ndpRAOptionsOffset is the start of the NDP options in an
   150  	// NDPRouterAdvert.
   151  	ndpRAOptionsOffset = 12
   152  )
   153  
   154  // CurrHopLimit returns the value of the Curr Hop Limit field.
   155  func (b NDPRouterAdvert) CurrHopLimit() uint8 {
   156  	return b[ndpRACurrHopLimitOffset]
   157  }
   158  
   159  // ManagedAddrConfFlag returns the value of the Managed Address Configuration
   160  // flag.
   161  func (b NDPRouterAdvert) ManagedAddrConfFlag() bool {
   162  	return b[ndpRAFlagsOffset]&ndpRAManagedAddrConfFlagMask != 0
   163  }
   164  
   165  // OtherConfFlag returns the value of the Other Configuration flag.
   166  func (b NDPRouterAdvert) OtherConfFlag() bool {
   167  	return b[ndpRAFlagsOffset]&ndpRAOtherConfFlagMask != 0
   168  }
   169  
   170  // DefaultRouterPreference returns the Default Router Preference field.
   171  func (b NDPRouterAdvert) DefaultRouterPreference() NDPRoutePreference {
   172  	return NDPRoutePreference((b[ndpRAFlagsOffset] & ndpDefaultRouterPreferenceMask) >> ndpDefaultRouterPreferenceShift)
   173  }
   174  
   175  // RouterLifetime returns the lifetime associated with the default router. A
   176  // value of 0 means the source of the Router Advertisement is not a default
   177  // router and SHOULD NOT appear on the default router list. Note, a value of 0
   178  // only means that the router should not be used as a default router, it does
   179  // not apply to other information contained in the Router Advertisement.
   180  func (b NDPRouterAdvert) RouterLifetime() time.Duration {
   181  	// The field is the time in seconds, as per RFC 4861 section 4.2.
   182  	return time.Second * time.Duration(binary.BigEndian.Uint16(b[ndpRARouterLifetimeOffset:]))
   183  }
   184  
   185  // ReachableTime returns the time that a node assumes a neighbor is reachable
   186  // after having received a reachability confirmation. A value of 0 means
   187  // that it is unspecified by the source of the Router Advertisement message.
   188  func (b NDPRouterAdvert) ReachableTime() time.Duration {
   189  	// The field is the time in milliseconds, as per RFC 4861 section 4.2.
   190  	return time.Millisecond * time.Duration(binary.BigEndian.Uint32(b[ndpRAReachableTimeOffset:]))
   191  }
   192  
   193  // RetransTimer returns the time between retransmitted Neighbor Solicitation
   194  // messages. A value of 0 means that it is unspecified by the source of the
   195  // Router Advertisement message.
   196  func (b NDPRouterAdvert) RetransTimer() time.Duration {
   197  	// The field is the time in milliseconds, as per RFC 4861 section 4.2.
   198  	return time.Millisecond * time.Duration(binary.BigEndian.Uint32(b[ndpRARetransTimerOffset:]))
   199  }
   200  
   201  // Options returns an NDPOptions of the options body.
   202  func (b NDPRouterAdvert) Options() NDPOptions {
   203  	return NDPOptions(b[ndpRAOptionsOffset:])
   204  }