inet.af/netstack@v0.0.0-20220214151720-7585b01ddccf/tcpip/header/ipv4.go (about)

     1  // Copyright 2021 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  	"inet.af/netstack/tcpip"
    23  )
    24  
    25  // RFC 971 defines the fields of the IPv4 header on page 11 using the following
    26  // diagram: ("Figure 4")
    27  //    0                   1                   2                   3
    28  //    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
    29  //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    30  //   |Version|  IHL  |Type of Service|          Total Length         |
    31  //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    32  //   |         Identification        |Flags|      Fragment Offset    |
    33  //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    34  //   |  Time to Live |    Protocol   |         Header Checksum       |
    35  //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    36  //   |                       Source Address                          |
    37  //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    38  //   |                    Destination Address                        |
    39  //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    40  //   |                    Options                    |    Padding    |
    41  //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    42  const (
    43  	versIHL = 0
    44  	tos     = 1
    45  	// IPv4TotalLenOffset is the offset of the total length field in the
    46  	// IPv4 header.
    47  	IPv4TotalLenOffset = 2
    48  	id                 = 4
    49  	flagsFO            = 6
    50  	ttl                = 8
    51  	protocol           = 9
    52  	checksum           = 10
    53  	srcAddr            = 12
    54  	dstAddr            = 16
    55  	options            = 20
    56  )
    57  
    58  // IPv4Fields contains the fields of an IPv4 packet. It is used to describe the
    59  // fields of a packet that needs to be encoded. The IHL field is not here as
    60  // it is totally defined by the size of the options.
    61  type IPv4Fields struct {
    62  	// TOS is the "type of service" field of an IPv4 packet.
    63  	TOS uint8
    64  
    65  	// TotalLength is the "total length" field of an IPv4 packet.
    66  	TotalLength uint16
    67  
    68  	// ID is the "identification" field of an IPv4 packet.
    69  	ID uint16
    70  
    71  	// Flags is the "flags" field of an IPv4 packet.
    72  	Flags uint8
    73  
    74  	// FragmentOffset is the "fragment offset" field of an IPv4 packet.
    75  	FragmentOffset uint16
    76  
    77  	// TTL is the "time to live" field of an IPv4 packet.
    78  	TTL uint8
    79  
    80  	// Protocol is the "protocol" field of an IPv4 packet.
    81  	Protocol uint8
    82  
    83  	// Checksum is the "checksum" field of an IPv4 packet.
    84  	Checksum uint16
    85  
    86  	// SrcAddr is the "source ip address" of an IPv4 packet.
    87  	SrcAddr tcpip.Address
    88  
    89  	// DstAddr is the "destination ip address" of an IPv4 packet.
    90  	DstAddr tcpip.Address
    91  
    92  	// Options must be 40 bytes or less as they must fit along with the
    93  	// rest of the IPv4 header into the maximum size describable in the
    94  	// IHL field. RFC 791 section 3.1 says:
    95  	//    IHL:  4 bits
    96  	//
    97  	//    Internet Header Length is the length of the internet header in 32
    98  	//    bit words, and thus points to the beginning of the data.  Note that
    99  	//    the minimum value for a correct header is 5.
   100  	//
   101  	// That leaves ten 32 bit (4 byte) fields for options. An attempt to encode
   102  	// more will fail.
   103  	Options IPv4OptionsSerializer
   104  }
   105  
   106  // IPv4 is an IPv4 header.
   107  // Most of the methods of IPv4 access to the underlying slice without
   108  // checking the boundaries and could panic because of 'index out of range'.
   109  // Always call IsValid() to validate an instance of IPv4 before using other
   110  // methods.
   111  type IPv4 []byte
   112  
   113  const (
   114  	// IPv4MinimumSize is the minimum size of a valid IPv4 packet;
   115  	// i.e. a packet header with no options.
   116  	IPv4MinimumSize = 20
   117  
   118  	// IPv4MaximumHeaderSize is the maximum size of an IPv4 header. Given
   119  	// that there are only 4 bits (max 0xF (15)) to represent the header length
   120  	// in 32-bit (4 byte) units, the header cannot exceed 15*4 = 60 bytes.
   121  	IPv4MaximumHeaderSize = 60
   122  
   123  	// IPv4MaximumOptionsSize is the largest size the IPv4 options can be.
   124  	IPv4MaximumOptionsSize = IPv4MaximumHeaderSize - IPv4MinimumSize
   125  
   126  	// IPv4MaximumPayloadSize is the maximum size of a valid IPv4 payload.
   127  	//
   128  	// Linux limits this to 65,515 octets (the max IP datagram size - the IPv4
   129  	// header size). But RFC 791 section 3.2 discusses the design of the IPv4
   130  	// fragment "allows 2**13 = 8192 fragments of 8 octets each for a total of
   131  	// 65,536 octets. Note that this is consistent with the datagram total
   132  	// length field (of course, the header is counted in the total length and not
   133  	// in the fragments)."
   134  	IPv4MaximumPayloadSize = 65536
   135  
   136  	// MinIPFragmentPayloadSize is the minimum number of payload bytes that
   137  	// the first fragment must carry when an IPv4 packet is fragmented.
   138  	MinIPFragmentPayloadSize = 8
   139  
   140  	// IPv4AddressSize is the size, in bytes, of an IPv4 address.
   141  	IPv4AddressSize = 4
   142  
   143  	// IPv4ProtocolNumber is IPv4's network protocol number.
   144  	IPv4ProtocolNumber tcpip.NetworkProtocolNumber = 0x0800
   145  
   146  	// IPv4Version is the version of the IPv4 protocol.
   147  	IPv4Version = 4
   148  
   149  	// IPv4AllSystems is the all systems IPv4 multicast address as per
   150  	// IANA's IPv4 Multicast Address Space Registry. See
   151  	// https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml.
   152  	IPv4AllSystems tcpip.Address = "\xe0\x00\x00\x01"
   153  
   154  	// IPv4Broadcast is the broadcast address of the IPv4 procotol.
   155  	IPv4Broadcast tcpip.Address = "\xff\xff\xff\xff"
   156  
   157  	// IPv4Any is the non-routable IPv4 "any" meta address.
   158  	IPv4Any tcpip.Address = "\x00\x00\x00\x00"
   159  
   160  	// IPv4AllRoutersGroup is a multicast address for all routers.
   161  	IPv4AllRoutersGroup tcpip.Address = "\xe0\x00\x00\x02"
   162  
   163  	// IPv4MinimumProcessableDatagramSize is the minimum size of an IP
   164  	// packet that every IPv4 capable host must be able to
   165  	// process/reassemble.
   166  	IPv4MinimumProcessableDatagramSize = 576
   167  
   168  	// IPv4MinimumMTU is the minimum MTU required by IPv4, per RFC 791,
   169  	// section 3.2:
   170  	//   Every internet module must be able to forward a datagram of 68 octets
   171  	//   without further fragmentation.  This is because an internet header may be
   172  	//   up to 60 octets, and the minimum fragment is 8 octets.
   173  	IPv4MinimumMTU = 68
   174  )
   175  
   176  // Flags that may be set in an IPv4 packet.
   177  const (
   178  	IPv4FlagMoreFragments = 1 << iota
   179  	IPv4FlagDontFragment
   180  )
   181  
   182  // ipv4LinkLocalUnicastSubnet is the IPv4 link local unicast subnet as defined
   183  // by RFC 3927 section 1.
   184  var ipv4LinkLocalUnicastSubnet = func() tcpip.Subnet {
   185  	subnet, err := tcpip.NewSubnet("\xa9\xfe\x00\x00", "\xff\xff\x00\x00")
   186  	if err != nil {
   187  		panic(err)
   188  	}
   189  	return subnet
   190  }()
   191  
   192  // ipv4LinkLocalMulticastSubnet is the IPv4 link local multicast subnet as
   193  // defined by RFC 5771 section 4.
   194  var ipv4LinkLocalMulticastSubnet = func() tcpip.Subnet {
   195  	subnet, err := tcpip.NewSubnet("\xe0\x00\x00\x00", "\xff\xff\xff\x00")
   196  	if err != nil {
   197  		panic(err)
   198  	}
   199  	return subnet
   200  }()
   201  
   202  // IPv4EmptySubnet is the empty IPv4 subnet.
   203  var IPv4EmptySubnet = func() tcpip.Subnet {
   204  	subnet, err := tcpip.NewSubnet(IPv4Any, tcpip.AddressMask(IPv4Any))
   205  	if err != nil {
   206  		panic(err)
   207  	}
   208  	return subnet
   209  }()
   210  
   211  // IPv4LoopbackSubnet is the loopback subnet for IPv4.
   212  var IPv4LoopbackSubnet = func() tcpip.Subnet {
   213  	subnet, err := tcpip.NewSubnet(tcpip.Address("\x7f\x00\x00\x00"), tcpip.AddressMask("\xff\x00\x00\x00"))
   214  	if err != nil {
   215  		panic(err)
   216  	}
   217  	return subnet
   218  }()
   219  
   220  // IPVersion returns the version of IP used in the given packet. It returns -1
   221  // if the packet is not large enough to contain the version field.
   222  func IPVersion(b []byte) int {
   223  	// Length must be at least offset+length of version field.
   224  	if len(b) < versIHL+1 {
   225  		return -1
   226  	}
   227  	return int(b[versIHL] >> ipVersionShift)
   228  }
   229  
   230  // RFC 791 page 11 shows the header length (IHL) is in the lower 4 bits
   231  // of the first byte, and is counted in multiples of 4 bytes.
   232  //
   233  //     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
   234  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   235  //    |Version|  IHL  |Type of Service|          Total Length         |
   236  //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   237  //      (...)
   238  //     Version:  4 bits
   239  //       The Version field indicates the format of the internet header.  This
   240  //       document describes version 4.
   241  //
   242  //     IHL:  4 bits
   243  //       Internet Header Length is the length of the internet header in 32
   244  //       bit words, and thus points to the beginning of the data.  Note that
   245  //       the minimum value for a correct header is 5.
   246  const (
   247  	ipVersionShift = 4
   248  	ipIHLMask      = 0x0f
   249  	IPv4IHLStride  = 4
   250  )
   251  
   252  // HeaderLength returns the value of the "header length" field of the IPv4
   253  // header. The length returned is in bytes.
   254  func (b IPv4) HeaderLength() uint8 {
   255  	return (b[versIHL] & ipIHLMask) * IPv4IHLStride
   256  }
   257  
   258  // SetHeaderLength sets the value of the "Internet Header Length" field.
   259  func (b IPv4) SetHeaderLength(hdrLen uint8) {
   260  	if hdrLen > IPv4MaximumHeaderSize {
   261  		panic(fmt.Sprintf("got IPv4 Header size = %d, want <= %d", hdrLen, IPv4MaximumHeaderSize))
   262  	}
   263  	b[versIHL] = (IPv4Version << ipVersionShift) | ((hdrLen / IPv4IHLStride) & ipIHLMask)
   264  }
   265  
   266  // ID returns the value of the identifier field of the IPv4 header.
   267  func (b IPv4) ID() uint16 {
   268  	return binary.BigEndian.Uint16(b[id:])
   269  }
   270  
   271  // Protocol returns the value of the protocol field of the IPv4 header.
   272  func (b IPv4) Protocol() uint8 {
   273  	return b[protocol]
   274  }
   275  
   276  // Flags returns the "flags" field of the IPv4 header.
   277  func (b IPv4) Flags() uint8 {
   278  	return uint8(binary.BigEndian.Uint16(b[flagsFO:]) >> 13)
   279  }
   280  
   281  // More returns whether the more fragments flag is set.
   282  func (b IPv4) More() bool {
   283  	return b.Flags()&IPv4FlagMoreFragments != 0
   284  }
   285  
   286  // TTL returns the "TTL" field of the IPv4 header.
   287  func (b IPv4) TTL() uint8 {
   288  	return b[ttl]
   289  }
   290  
   291  // FragmentOffset returns the "fragment offset" field of the IPv4 header.
   292  func (b IPv4) FragmentOffset() uint16 {
   293  	return binary.BigEndian.Uint16(b[flagsFO:]) << 3
   294  }
   295  
   296  // TotalLength returns the "total length" field of the IPv4 header.
   297  func (b IPv4) TotalLength() uint16 {
   298  	return binary.BigEndian.Uint16(b[IPv4TotalLenOffset:])
   299  }
   300  
   301  // Checksum returns the checksum field of the IPv4 header.
   302  func (b IPv4) Checksum() uint16 {
   303  	return binary.BigEndian.Uint16(b[checksum:])
   304  }
   305  
   306  // SourceAddress returns the "source address" field of the IPv4 header.
   307  func (b IPv4) SourceAddress() tcpip.Address {
   308  	return tcpip.Address(b[srcAddr : srcAddr+IPv4AddressSize])
   309  }
   310  
   311  // DestinationAddress returns the "destination address" field of the IPv4
   312  // header.
   313  func (b IPv4) DestinationAddress() tcpip.Address {
   314  	return tcpip.Address(b[dstAddr : dstAddr+IPv4AddressSize])
   315  }
   316  
   317  // SetSourceAddressWithChecksumUpdate implements ChecksummableNetwork.
   318  func (b IPv4) SetSourceAddressWithChecksumUpdate(new tcpip.Address) {
   319  	b.SetChecksum(^checksumUpdate2ByteAlignedAddress(^b.Checksum(), b.SourceAddress(), new))
   320  	b.SetSourceAddress(new)
   321  }
   322  
   323  // SetDestinationAddressWithChecksumUpdate implements ChecksummableNetwork.
   324  func (b IPv4) SetDestinationAddressWithChecksumUpdate(new tcpip.Address) {
   325  	b.SetChecksum(^checksumUpdate2ByteAlignedAddress(^b.Checksum(), b.DestinationAddress(), new))
   326  	b.SetDestinationAddress(new)
   327  }
   328  
   329  // padIPv4OptionsLength returns the total length for IPv4 options of length l
   330  // after applying padding according to RFC 791:
   331  //    The internet header padding is used to ensure that the internet
   332  //    header ends on a 32 bit boundary.
   333  func padIPv4OptionsLength(length uint8) uint8 {
   334  	return (length + IPv4IHLStride - 1) & ^uint8(IPv4IHLStride-1)
   335  }
   336  
   337  // IPv4Options is a buffer that holds all the raw IP options.
   338  type IPv4Options []byte
   339  
   340  // Options returns a buffer holding the options.
   341  func (b IPv4) Options() IPv4Options {
   342  	hdrLen := b.HeaderLength()
   343  	return IPv4Options(b[options:hdrLen:hdrLen])
   344  }
   345  
   346  // TransportProtocol implements Network.TransportProtocol.
   347  func (b IPv4) TransportProtocol() tcpip.TransportProtocolNumber {
   348  	return tcpip.TransportProtocolNumber(b.Protocol())
   349  }
   350  
   351  // Payload implements Network.Payload.
   352  func (b IPv4) Payload() []byte {
   353  	return b[b.HeaderLength():][:b.PayloadLength()]
   354  }
   355  
   356  // PayloadLength returns the length of the payload portion of the IPv4 packet.
   357  func (b IPv4) PayloadLength() uint16 {
   358  	return b.TotalLength() - uint16(b.HeaderLength())
   359  }
   360  
   361  // TOS returns the "type of service" field of the IPv4 header.
   362  func (b IPv4) TOS() (uint8, uint32) {
   363  	return b[tos], 0
   364  }
   365  
   366  // SetTOS sets the "type of service" field of the IPv4 header.
   367  func (b IPv4) SetTOS(v uint8, _ uint32) {
   368  	b[tos] = v
   369  }
   370  
   371  // SetTTL sets the "Time to Live" field of the IPv4 header.
   372  func (b IPv4) SetTTL(v byte) {
   373  	b[ttl] = v
   374  }
   375  
   376  // SetTotalLength sets the "total length" field of the IPv4 header.
   377  func (b IPv4) SetTotalLength(totalLength uint16) {
   378  	binary.BigEndian.PutUint16(b[IPv4TotalLenOffset:], totalLength)
   379  }
   380  
   381  // SetChecksum sets the checksum field of the IPv4 header.
   382  func (b IPv4) SetChecksum(v uint16) {
   383  	binary.BigEndian.PutUint16(b[checksum:], v)
   384  }
   385  
   386  // SetFlagsFragmentOffset sets the "flags" and "fragment offset" fields of the
   387  // IPv4 header.
   388  func (b IPv4) SetFlagsFragmentOffset(flags uint8, offset uint16) {
   389  	v := (uint16(flags) << 13) | (offset >> 3)
   390  	binary.BigEndian.PutUint16(b[flagsFO:], v)
   391  }
   392  
   393  // SetID sets the identification field.
   394  func (b IPv4) SetID(v uint16) {
   395  	binary.BigEndian.PutUint16(b[id:], v)
   396  }
   397  
   398  // SetSourceAddress sets the "source address" field of the IPv4 header.
   399  func (b IPv4) SetSourceAddress(addr tcpip.Address) {
   400  	copy(b[srcAddr:srcAddr+IPv4AddressSize], addr)
   401  }
   402  
   403  // SetDestinationAddress sets the "destination address" field of the IPv4
   404  // header.
   405  func (b IPv4) SetDestinationAddress(addr tcpip.Address) {
   406  	copy(b[dstAddr:dstAddr+IPv4AddressSize], addr)
   407  }
   408  
   409  // CalculateChecksum calculates the checksum of the IPv4 header.
   410  func (b IPv4) CalculateChecksum() uint16 {
   411  	return Checksum(b[:b.HeaderLength()], 0)
   412  }
   413  
   414  // Encode encodes all the fields of the IPv4 header.
   415  func (b IPv4) Encode(i *IPv4Fields) {
   416  	// The size of the options defines the size of the whole header and thus the
   417  	// IHL field. Options are rare and this is a heavily used function so it is
   418  	// worth a bit of optimisation here to keep the serializer out of the fast
   419  	// path.
   420  	hdrLen := uint8(IPv4MinimumSize)
   421  	if len(i.Options) != 0 {
   422  		hdrLen += i.Options.Serialize(b[options:])
   423  	}
   424  	if hdrLen > IPv4MaximumHeaderSize {
   425  		panic(fmt.Sprintf("%d is larger than maximum IPv4 header size of %d", hdrLen, IPv4MaximumHeaderSize))
   426  	}
   427  	b.SetHeaderLength(hdrLen)
   428  	b[tos] = i.TOS
   429  	b.SetTotalLength(i.TotalLength)
   430  	binary.BigEndian.PutUint16(b[id:], i.ID)
   431  	b.SetFlagsFragmentOffset(i.Flags, i.FragmentOffset)
   432  	b[ttl] = i.TTL
   433  	b[protocol] = i.Protocol
   434  	b.SetChecksum(i.Checksum)
   435  	copy(b[srcAddr:srcAddr+IPv4AddressSize], i.SrcAddr)
   436  	copy(b[dstAddr:dstAddr+IPv4AddressSize], i.DstAddr)
   437  }
   438  
   439  // EncodePartial updates the total length and checksum fields of IPv4 header,
   440  // taking in the partial checksum, which is the checksum of the header without
   441  // the total length and checksum fields. It is useful in cases when similar
   442  // packets are produced.
   443  func (b IPv4) EncodePartial(partialChecksum, totalLength uint16) {
   444  	b.SetTotalLength(totalLength)
   445  	checksum := Checksum(b[IPv4TotalLenOffset:IPv4TotalLenOffset+2], partialChecksum)
   446  	b.SetChecksum(^checksum)
   447  }
   448  
   449  // IsValid performs basic validation on the packet.
   450  func (b IPv4) IsValid(pktSize int) bool {
   451  	if len(b) < IPv4MinimumSize {
   452  		return false
   453  	}
   454  
   455  	hlen := int(b.HeaderLength())
   456  	tlen := int(b.TotalLength())
   457  	if hlen < IPv4MinimumSize || hlen > tlen || tlen > pktSize {
   458  		return false
   459  	}
   460  
   461  	if IPVersion(b) != IPv4Version {
   462  		return false
   463  	}
   464  
   465  	return true
   466  }
   467  
   468  // IsV4LinkLocalUnicastAddress determines if the provided address is an IPv4
   469  // link-local unicast address.
   470  func IsV4LinkLocalUnicastAddress(addr tcpip.Address) bool {
   471  	return ipv4LinkLocalUnicastSubnet.Contains(addr)
   472  }
   473  
   474  // IsV4LinkLocalMulticastAddress determines if the provided address is an IPv4
   475  // link-local multicast address.
   476  func IsV4LinkLocalMulticastAddress(addr tcpip.Address) bool {
   477  	return ipv4LinkLocalMulticastSubnet.Contains(addr)
   478  }
   479  
   480  // IsChecksumValid returns true iff the IPv4 header's checksum is valid.
   481  func (b IPv4) IsChecksumValid() bool {
   482  	// There has been some confusion regarding verifying checksums. We need
   483  	// just look for negative 0 (0xffff) as the checksum, as it's not possible to
   484  	// get positive 0 (0) for the checksum. Some bad implementations could get it
   485  	// when doing entry replacement in the early days of the Internet,
   486  	// however the lore that one needs to check for both persists.
   487  	//
   488  	// RFC 1624 section 1 describes the source of this confusion as:
   489  	//     [the partial recalculation method described in RFC 1071] computes a
   490  	//     result for certain cases that differs from the one obtained from
   491  	//     scratch (one's complement of one's complement sum of the original
   492  	//     fields).
   493  	//
   494  	// However RFC 1624 section 5 clarifies that if using the verification method
   495  	// "recommended by RFC 1071, it does not matter if an intermediate system
   496  	// generated a -0 instead of +0".
   497  	//
   498  	// RFC1071 page 1 specifies the verification method as:
   499  	//	  (3)  To check a checksum, the 1's complement sum is computed over the
   500  	//        same set of octets, including the checksum field.  If the result
   501  	//        is all 1 bits (-0 in 1's complement arithmetic), the check
   502  	//        succeeds.
   503  	return b.CalculateChecksum() == 0xffff
   504  }
   505  
   506  // IsV4MulticastAddress determines if the provided address is an IPv4 multicast
   507  // address (range 224.0.0.0 to 239.255.255.255). The four most significant bits
   508  // will be 1110 = 0xe0.
   509  func IsV4MulticastAddress(addr tcpip.Address) bool {
   510  	if len(addr) != IPv4AddressSize {
   511  		return false
   512  	}
   513  	return (addr[0] & 0xf0) == 0xe0
   514  }
   515  
   516  // IsV4LoopbackAddress determines if the provided address is an IPv4 loopback
   517  // address (belongs to 127.0.0.0/8 subnet). See RFC 1122 section 3.2.1.3.
   518  func IsV4LoopbackAddress(addr tcpip.Address) bool {
   519  	if len(addr) != IPv4AddressSize {
   520  		return false
   521  	}
   522  	return addr[0] == 0x7f
   523  }
   524  
   525  // ========================= Options ==========================
   526  
   527  // An IPv4OptionType can hold the valuse for the Type in an IPv4 option.
   528  type IPv4OptionType byte
   529  
   530  // These constants are needed to identify individual options in the option list.
   531  // While RFC 791 (page 31) says "Every internet module must be able to act on
   532  // every option." This has not generally been adhered to and some options have
   533  // very low rates of support. We do not support options other than those shown
   534  // below.
   535  
   536  const (
   537  	// IPv4OptionListEndType is the option type for the End Of Option List
   538  	// option. Anything following is ignored.
   539  	IPv4OptionListEndType IPv4OptionType = 0
   540  
   541  	// IPv4OptionNOPType is the No-Operation option. May appear between other
   542  	// options and may appear multiple times.
   543  	IPv4OptionNOPType IPv4OptionType = 1
   544  
   545  	// IPv4OptionRouterAlertType is the option type for the Router Alert option,
   546  	// defined in RFC 2113 Section 2.1.
   547  	IPv4OptionRouterAlertType IPv4OptionType = 20 | 0x80
   548  
   549  	// IPv4OptionRecordRouteType is used by each router on the path of the packet
   550  	// to record its path. It is carried over to an Echo Reply.
   551  	IPv4OptionRecordRouteType IPv4OptionType = 7
   552  
   553  	// IPv4OptionTimestampType is the option type for the Timestamp option.
   554  	IPv4OptionTimestampType IPv4OptionType = 68
   555  
   556  	// ipv4OptionTypeOffset is the offset in an option of its type field.
   557  	ipv4OptionTypeOffset = 0
   558  
   559  	// IPv4OptionLengthOffset is the offset in an option of its length field.
   560  	IPv4OptionLengthOffset = 1
   561  )
   562  
   563  // IPv4OptParameterProblem indicates that a Parameter Problem message
   564  // should be generated, and gives the offset in the current entity
   565  // that should be used in that packet.
   566  type IPv4OptParameterProblem struct {
   567  	Pointer  uint8
   568  	NeedICMP bool
   569  }
   570  
   571  // IPv4Option is an interface representing various option types.
   572  type IPv4Option interface {
   573  	// Type returns the type identifier of the option.
   574  	Type() IPv4OptionType
   575  
   576  	// Size returns the size of the option in bytes.
   577  	Size() uint8
   578  
   579  	// Contents returns a slice holding the contents of the option.
   580  	Contents() []byte
   581  }
   582  
   583  var _ IPv4Option = (*IPv4OptionGeneric)(nil)
   584  
   585  // IPv4OptionGeneric is an IPv4 Option of unknown type.
   586  type IPv4OptionGeneric []byte
   587  
   588  // Type implements IPv4Option.
   589  func (o *IPv4OptionGeneric) Type() IPv4OptionType {
   590  	return IPv4OptionType((*o)[ipv4OptionTypeOffset])
   591  }
   592  
   593  // Size implements IPv4Option.
   594  func (o *IPv4OptionGeneric) Size() uint8 { return uint8(len(*o)) }
   595  
   596  // Contents implements IPv4Option.
   597  func (o *IPv4OptionGeneric) Contents() []byte { return *o }
   598  
   599  // IPv4OptionIterator is an iterator pointing to a specific IP option
   600  // at any point of time. It also holds information as to a new options buffer
   601  // that we are building up to hand back to the caller.
   602  // TODO(https://gvisor.dev/issues/5513): Add unit tests for IPv4OptionIterator.
   603  type IPv4OptionIterator struct {
   604  	options IPv4Options
   605  	// ErrCursor is where we are while parsing options. It is exported as any
   606  	// resulting ICMP packet is supposed to have a pointer to the byte within
   607  	// the IP packet where the error was detected.
   608  	ErrCursor     uint8
   609  	nextErrCursor uint8
   610  	newOptions    [IPv4MaximumOptionsSize]byte
   611  	writePoint    int
   612  }
   613  
   614  // MakeIterator sets up and returns an iterator of options. It also sets up the
   615  // building of a new option set.
   616  func (o IPv4Options) MakeIterator() IPv4OptionIterator {
   617  	return IPv4OptionIterator{
   618  		options:       o,
   619  		nextErrCursor: IPv4MinimumSize,
   620  	}
   621  }
   622  
   623  // InitReplacement copies the option into the new option buffer.
   624  func (i *IPv4OptionIterator) InitReplacement(option IPv4Option) IPv4Options {
   625  	replacementOption := i.RemainingBuffer()[:option.Size()]
   626  	if copied := copy(replacementOption, option.Contents()); copied != len(replacementOption) {
   627  		panic(fmt.Sprintf("copied %d bytes in the replacement option buffer, expected %d bytes", copied, len(replacementOption)))
   628  	}
   629  	return replacementOption
   630  }
   631  
   632  // RemainingBuffer returns the remaining (unused) part of the new option buffer,
   633  // into which a new option may be written.
   634  func (i *IPv4OptionIterator) RemainingBuffer() IPv4Options {
   635  	return i.newOptions[i.writePoint:]
   636  }
   637  
   638  // ConsumeBuffer marks a portion of the new buffer as used.
   639  func (i *IPv4OptionIterator) ConsumeBuffer(size int) {
   640  	i.writePoint += size
   641  }
   642  
   643  // PushNOPOrEnd puts one of the single byte options onto the new options.
   644  // Only values 0 or 1 (ListEnd or NOP) are valid input.
   645  func (i *IPv4OptionIterator) PushNOPOrEnd(val IPv4OptionType) {
   646  	if val > IPv4OptionNOPType {
   647  		panic(fmt.Sprintf("invalid option type %d pushed onto option build buffer", val))
   648  	}
   649  	i.newOptions[i.writePoint] = byte(val)
   650  	i.writePoint++
   651  }
   652  
   653  // Finalize returns the completed replacement options buffer padded
   654  // as needed.
   655  func (i *IPv4OptionIterator) Finalize() IPv4Options {
   656  	// RFC 791 page 31 says:
   657  	//     The options might not end on a 32-bit boundary.  The internet header
   658  	//     must be filled out with octets of zeros.  The first of these would
   659  	//     be interpreted as the end-of-options option, and the remainder as
   660  	//     internet header padding.
   661  	// Since the buffer is already zero filled we just need to step the write
   662  	// pointer up to the next multiple of 4.
   663  	options := IPv4Options(i.newOptions[:(i.writePoint+0x3) & ^0x3])
   664  	// Poison the write pointer.
   665  	i.writePoint = len(i.newOptions)
   666  	return options
   667  }
   668  
   669  // Next returns the next IP option in the buffer/list of IP options.
   670  // It returns
   671  // - A slice of bytes holding the next option or nil if there is error.
   672  // - A boolean which is true if parsing of all the options is complete.
   673  //   Undefined in the case of error.
   674  // - An error indication which is non-nil if an error condition was found.
   675  func (i *IPv4OptionIterator) Next() (IPv4Option, bool, *IPv4OptParameterProblem) {
   676  	// The opts slice gets shorter as we process the options. When we have no
   677  	// bytes left we are done.
   678  	if len(i.options) == 0 {
   679  		return nil, true, nil
   680  	}
   681  
   682  	i.ErrCursor = i.nextErrCursor
   683  
   684  	optType := IPv4OptionType(i.options[ipv4OptionTypeOffset])
   685  
   686  	if optType == IPv4OptionNOPType || optType == IPv4OptionListEndType {
   687  		optionBody := i.options[:1]
   688  		i.options = i.options[1:]
   689  		i.nextErrCursor = i.ErrCursor + 1
   690  		retval := IPv4OptionGeneric(optionBody)
   691  		return &retval, false, nil
   692  	}
   693  
   694  	// There are no more single byte options defined.  All the rest have a length
   695  	// field so we need to sanity check it.
   696  	if len(i.options) == 1 {
   697  		return nil, false, &IPv4OptParameterProblem{
   698  			Pointer:  i.ErrCursor,
   699  			NeedICMP: true,
   700  		}
   701  	}
   702  
   703  	optLen := i.options[IPv4OptionLengthOffset]
   704  
   705  	if optLen <= IPv4OptionLengthOffset || optLen > uint8(len(i.options)) {
   706  		// The actual error is in the length (2nd byte of the option) but we
   707  		// return the start of the option for compatibility with Linux.
   708  
   709  		return nil, false, &IPv4OptParameterProblem{
   710  			Pointer:  i.ErrCursor,
   711  			NeedICMP: true,
   712  		}
   713  	}
   714  
   715  	optionBody := i.options[:optLen]
   716  	i.nextErrCursor = i.ErrCursor + optLen
   717  	i.options = i.options[optLen:]
   718  
   719  	// Check the length of some option types that we know.
   720  	switch optType {
   721  	case IPv4OptionTimestampType:
   722  		if optLen < IPv4OptionTimestampHdrLength {
   723  			i.ErrCursor++
   724  			return nil, false, &IPv4OptParameterProblem{
   725  				Pointer:  i.ErrCursor,
   726  				NeedICMP: true,
   727  			}
   728  		}
   729  		retval := IPv4OptionTimestamp(optionBody)
   730  		return &retval, false, nil
   731  
   732  	case IPv4OptionRecordRouteType:
   733  		if optLen < IPv4OptionRecordRouteHdrLength {
   734  			i.ErrCursor++
   735  			return nil, false, &IPv4OptParameterProblem{
   736  				Pointer:  i.ErrCursor,
   737  				NeedICMP: true,
   738  			}
   739  		}
   740  		retval := IPv4OptionRecordRoute(optionBody)
   741  		return &retval, false, nil
   742  
   743  	case IPv4OptionRouterAlertType:
   744  		if optLen != IPv4OptionRouterAlertLength {
   745  			i.ErrCursor++
   746  			return nil, false, &IPv4OptParameterProblem{
   747  				Pointer:  i.ErrCursor,
   748  				NeedICMP: true,
   749  			}
   750  		}
   751  		retval := IPv4OptionRouterAlert(optionBody)
   752  		return &retval, false, nil
   753  	}
   754  	retval := IPv4OptionGeneric(optionBody)
   755  	return &retval, false, nil
   756  }
   757  
   758  //
   759  // IP Timestamp option - RFC 791 page 22.
   760  // +--------+--------+--------+--------+
   761  // |01000100| length | pointer|oflw|flg|
   762  // +--------+--------+--------+--------+
   763  // |         internet address          |
   764  // +--------+--------+--------+--------+
   765  // |             timestamp             |
   766  // +--------+--------+--------+--------+
   767  // |                ...                |
   768  //
   769  // Type = 68
   770  //
   771  // The Option Length is the number of octets in the option counting
   772  // the type, length, pointer, and overflow/flag octets (maximum
   773  // length 40).
   774  //
   775  // The Pointer is the number of octets from the beginning of this
   776  // option to the end of timestamps plus one (i.e., it points to the
   777  // octet beginning the space for next timestamp).  The smallest
   778  // legal value is 5.  The timestamp area is full when the pointer
   779  // is greater than the length.
   780  //
   781  // The Overflow (oflw) [4 bits] is the number of IP modules that
   782  // cannot register timestamps due to lack of space.
   783  //
   784  // The Flag (flg) [4 bits] values are
   785  //
   786  //   0 -- time stamps only, stored in consecutive 32-bit words,
   787  //
   788  //   1 -- each timestamp is preceded with internet address of the
   789  //        registering entity,
   790  //
   791  //   3 -- the internet address fields are prespecified.  An IP
   792  //        module only registers its timestamp if it matches its own
   793  //        address with the next specified internet address.
   794  //
   795  // Timestamps are defined in RFC 791 page 22 as milliseconds since midnight UTC.
   796  //
   797  //        The Timestamp is a right-justified, 32-bit timestamp in
   798  //        milliseconds since midnight UT.  If the time is not available in
   799  //        milliseconds or cannot be provided with respect to midnight UT
   800  //        then any time may be inserted as a timestamp provided the high
   801  //        order bit of the timestamp field is set to one to indicate the
   802  //        use of a non-standard value.
   803  
   804  // IPv4OptTSFlags sefines the values expected in the Timestamp
   805  // option Flags field.
   806  type IPv4OptTSFlags uint8
   807  
   808  //
   809  // Timestamp option specific related constants.
   810  const (
   811  	// IPv4OptionTimestampHdrLength is the length of the timestamp option header.
   812  	IPv4OptionTimestampHdrLength = 4
   813  
   814  	// IPv4OptionTimestampSize is the size of an IP timestamp.
   815  	IPv4OptionTimestampSize = 4
   816  
   817  	// IPv4OptionTimestampWithAddrSize is the size of an IP timestamp + Address.
   818  	IPv4OptionTimestampWithAddrSize = IPv4AddressSize + IPv4OptionTimestampSize
   819  
   820  	// IPv4OptionTimestampMaxSize is limited by space for options
   821  	IPv4OptionTimestampMaxSize = IPv4MaximumOptionsSize
   822  
   823  	// IPv4OptionTimestampOnlyFlag is a flag indicating that only timestamp
   824  	// is present.
   825  	IPv4OptionTimestampOnlyFlag IPv4OptTSFlags = 0
   826  
   827  	// IPv4OptionTimestampWithIPFlag is a flag indicating that both timestamps and
   828  	// IP are present.
   829  	IPv4OptionTimestampWithIPFlag IPv4OptTSFlags = 1
   830  
   831  	// IPv4OptionTimestampWithPredefinedIPFlag is a flag indicating that
   832  	// predefined IP is present.
   833  	IPv4OptionTimestampWithPredefinedIPFlag IPv4OptTSFlags = 3
   834  )
   835  
   836  // ipv4TimestampTime provides the current time as specified in RFC 791.
   837  func ipv4TimestampTime(clock tcpip.Clock) uint32 {
   838  	// Per RFC 791 page 21:
   839  	//   The Timestamp is a right-justified, 32-bit timestamp in
   840  	//   milliseconds since midnight UT.
   841  	now := clock.Now().UTC()
   842  	midnight := now.Truncate(24 * time.Hour)
   843  	return uint32(now.Sub(midnight).Milliseconds())
   844  }
   845  
   846  // IP Timestamp option fields.
   847  const (
   848  	// IPv4OptTSPointerOffset is the offset of the Timestamp pointer field.
   849  	IPv4OptTSPointerOffset = 2
   850  
   851  	// IPv4OptTSPointerOffset is the offset of the combined Flag and Overflow
   852  	// fields, (each being 4 bits).
   853  	IPv4OptTSOFLWAndFLGOffset = 3
   854  	// These constants define the sub byte fields of the Flag and OverFlow field.
   855  	ipv4OptionTimestampOverflowshift      = 4
   856  	ipv4OptionTimestampFlagsMask     byte = 0x0f
   857  )
   858  
   859  var _ IPv4Option = (*IPv4OptionTimestamp)(nil)
   860  
   861  // IPv4OptionTimestamp is a Timestamp option from RFC 791.
   862  type IPv4OptionTimestamp []byte
   863  
   864  // Type implements IPv4Option.Type().
   865  func (ts *IPv4OptionTimestamp) Type() IPv4OptionType { return IPv4OptionTimestampType }
   866  
   867  // Size implements IPv4Option.
   868  func (ts *IPv4OptionTimestamp) Size() uint8 { return uint8(len(*ts)) }
   869  
   870  // Contents implements IPv4Option.
   871  func (ts *IPv4OptionTimestamp) Contents() []byte { return *ts }
   872  
   873  // Pointer returns the pointer field in the IP Timestamp option.
   874  func (ts *IPv4OptionTimestamp) Pointer() uint8 {
   875  	return (*ts)[IPv4OptTSPointerOffset]
   876  }
   877  
   878  // Flags returns the flags field in the IP Timestamp option.
   879  func (ts *IPv4OptionTimestamp) Flags() IPv4OptTSFlags {
   880  	return IPv4OptTSFlags((*ts)[IPv4OptTSOFLWAndFLGOffset] & ipv4OptionTimestampFlagsMask)
   881  }
   882  
   883  // Overflow returns the Overflow field in the IP Timestamp option.
   884  func (ts *IPv4OptionTimestamp) Overflow() uint8 {
   885  	return (*ts)[IPv4OptTSOFLWAndFLGOffset] >> ipv4OptionTimestampOverflowshift
   886  }
   887  
   888  // IncOverflow increments the Overflow field in the IP Timestamp option. It
   889  // returns the incremented value. If the return value is 0 then the field
   890  // overflowed.
   891  func (ts *IPv4OptionTimestamp) IncOverflow() uint8 {
   892  	(*ts)[IPv4OptTSOFLWAndFLGOffset] += 1 << ipv4OptionTimestampOverflowshift
   893  	return ts.Overflow()
   894  }
   895  
   896  // UpdateTimestamp updates the fields of the next free timestamp slot.
   897  func (ts *IPv4OptionTimestamp) UpdateTimestamp(addr tcpip.Address, clock tcpip.Clock) {
   898  	slot := (*ts)[ts.Pointer()-1:]
   899  
   900  	switch ts.Flags() {
   901  	case IPv4OptionTimestampOnlyFlag:
   902  		binary.BigEndian.PutUint32(slot, ipv4TimestampTime(clock))
   903  		(*ts)[IPv4OptTSPointerOffset] += IPv4OptionTimestampSize
   904  	case IPv4OptionTimestampWithIPFlag:
   905  		if n := copy(slot, addr); n != IPv4AddressSize {
   906  			panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, IPv4AddressSize))
   907  		}
   908  		binary.BigEndian.PutUint32(slot[IPv4AddressSize:], ipv4TimestampTime(clock))
   909  		(*ts)[IPv4OptTSPointerOffset] += IPv4OptionTimestampWithAddrSize
   910  	case IPv4OptionTimestampWithPredefinedIPFlag:
   911  		if tcpip.Address(slot[:IPv4AddressSize]) == addr {
   912  			binary.BigEndian.PutUint32(slot[IPv4AddressSize:], ipv4TimestampTime(clock))
   913  			(*ts)[IPv4OptTSPointerOffset] += IPv4OptionTimestampWithAddrSize
   914  		}
   915  	}
   916  }
   917  
   918  // RecordRoute option specific related constants.
   919  //
   920  // from RFC 791 page 20:
   921  //   Record Route
   922  //
   923  //         +--------+--------+--------+---------//--------+
   924  //         |00000111| length | pointer|     route data    |
   925  //         +--------+--------+--------+---------//--------+
   926  //           Type=7
   927  //
   928  //         The record route option provides a means to record the route of
   929  //         an internet datagram.
   930  //
   931  //         The option begins with the option type code.  The second octet
   932  //         is the option length which includes the option type code and the
   933  //         length octet, the pointer octet, and length-3 octets of route
   934  //         data.  The third octet is the pointer into the route data
   935  //         indicating the octet which begins the next area to store a route
   936  //         address.  The pointer is relative to this option, and the
   937  //         smallest legal value for the pointer is 4.
   938  const (
   939  	// IPv4OptionRecordRouteHdrLength is the length of the Record Route option
   940  	// header.
   941  	IPv4OptionRecordRouteHdrLength = 3
   942  
   943  	// IPv4OptRRPointerOffset is the offset to the pointer field in an RR
   944  	// option, which points to the next free slot in the list of addresses.
   945  	IPv4OptRRPointerOffset = 2
   946  )
   947  
   948  var _ IPv4Option = (*IPv4OptionRecordRoute)(nil)
   949  
   950  // IPv4OptionRecordRoute is an IPv4 RecordRoute option defined by RFC 791.
   951  type IPv4OptionRecordRoute []byte
   952  
   953  // Pointer returns the pointer field in the IP RecordRoute option.
   954  func (rr *IPv4OptionRecordRoute) Pointer() uint8 {
   955  	return (*rr)[IPv4OptRRPointerOffset]
   956  }
   957  
   958  // StoreAddress stores the given IPv4 address into the next free slot.
   959  func (rr *IPv4OptionRecordRoute) StoreAddress(addr tcpip.Address) {
   960  	start := rr.Pointer() - 1 // A one based number.
   961  	// start and room checked by caller.
   962  	if n := copy((*rr)[start:], addr); n != IPv4AddressSize {
   963  		panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, IPv4AddressSize))
   964  	}
   965  	(*rr)[IPv4OptRRPointerOffset] += IPv4AddressSize
   966  }
   967  
   968  // Type implements IPv4Option.
   969  func (rr *IPv4OptionRecordRoute) Type() IPv4OptionType { return IPv4OptionRecordRouteType }
   970  
   971  // Size implements IPv4Option.
   972  func (rr *IPv4OptionRecordRoute) Size() uint8 { return uint8(len(*rr)) }
   973  
   974  // Contents implements IPv4Option.
   975  func (rr *IPv4OptionRecordRoute) Contents() []byte { return *rr }
   976  
   977  // Router Alert option specific related constants.
   978  //
   979  // from RFC 2113 section 2.1:
   980  //
   981  //     +--------+--------+--------+--------+
   982  //     |10010100|00000100|  2 octet value  |
   983  //     +--------+--------+--------+--------+
   984  //
   985  //     Type:
   986  //     Copied flag:  1 (all fragments must carry the option)
   987  //     Option class: 0 (control)
   988  //     Option number: 20 (decimal)
   989  //
   990  //     Length: 4
   991  //
   992  //     Value:  A two octet code with the following values:
   993  //     0 - Router shall examine packet
   994  //     1-65535 - Reserved
   995  const (
   996  	// IPv4OptionRouterAlertLength is the length of a Router Alert option.
   997  	IPv4OptionRouterAlertLength = 4
   998  
   999  	// IPv4OptionRouterAlertValue is the only permissible value of the 16 bit
  1000  	// payload of the router alert option.
  1001  	IPv4OptionRouterAlertValue = 0
  1002  
  1003  	// IPv4OptionRouterAlertValueOffset is the offset for the value of a
  1004  	// RouterAlert option.
  1005  	IPv4OptionRouterAlertValueOffset = 2
  1006  )
  1007  
  1008  var _ IPv4Option = (*IPv4OptionRouterAlert)(nil)
  1009  
  1010  // IPv4OptionRouterAlert is an IPv4 RouterAlert option defined by RFC 2113.
  1011  type IPv4OptionRouterAlert []byte
  1012  
  1013  // Type implements IPv4Option.
  1014  func (*IPv4OptionRouterAlert) Type() IPv4OptionType { return IPv4OptionRouterAlertType }
  1015  
  1016  // Size implements IPv4Option.
  1017  func (ra *IPv4OptionRouterAlert) Size() uint8 { return uint8(len(*ra)) }
  1018  
  1019  // Contents implements IPv4Option.
  1020  func (ra *IPv4OptionRouterAlert) Contents() []byte { return *ra }
  1021  
  1022  // Value returns the value of the IPv4OptionRouterAlert.
  1023  func (ra *IPv4OptionRouterAlert) Value() uint16 {
  1024  	return binary.BigEndian.Uint16(ra.Contents()[IPv4OptionRouterAlertValueOffset:])
  1025  }
  1026  
  1027  // IPv4SerializableOption is an interface to represent serializable IPv4 option
  1028  // types.
  1029  type IPv4SerializableOption interface {
  1030  	// optionType returns the type identifier of the option.
  1031  	optionType() IPv4OptionType
  1032  }
  1033  
  1034  // IPv4SerializableOptionPayload is an interface providing serialization of the
  1035  // payload of an IPv4 option.
  1036  type IPv4SerializableOptionPayload interface {
  1037  	// length returns the size of the payload.
  1038  	length() uint8
  1039  
  1040  	// serializeInto serializes the payload into the provided byte buffer.
  1041  	//
  1042  	// Note, the caller MUST provide a byte buffer with size of at least
  1043  	// Length. Implementers of this function may assume that the byte buffer
  1044  	// is of sufficient size. serializeInto MUST panic if the provided byte
  1045  	// buffer is not of sufficient size.
  1046  	//
  1047  	// serializeInto will return the number of bytes that was used to
  1048  	// serialize the receiver. Implementers must only use the number of
  1049  	// bytes required to serialize the receiver. Callers MAY provide a
  1050  	// larger buffer than required to serialize into.
  1051  	serializeInto(buffer []byte) uint8
  1052  }
  1053  
  1054  // IPv4OptionsSerializer is a serializer for IPv4 options.
  1055  type IPv4OptionsSerializer []IPv4SerializableOption
  1056  
  1057  // Length returns the total number of bytes required to serialize the options.
  1058  func (s IPv4OptionsSerializer) Length() uint8 {
  1059  	var total uint8
  1060  	for _, opt := range s {
  1061  		total++
  1062  		if withPayload, ok := opt.(IPv4SerializableOptionPayload); ok {
  1063  			// Add 1 to reported length to account for the length byte.
  1064  			total += 1 + withPayload.length()
  1065  		}
  1066  	}
  1067  	return padIPv4OptionsLength(total)
  1068  }
  1069  
  1070  // Serialize serializes the provided list of IPV4 options into b.
  1071  //
  1072  // Note, b must be of sufficient size to hold all the options in s. See
  1073  // IPv4OptionsSerializer.Length for details on the getting the total size
  1074  // of a serialized IPv4OptionsSerializer.
  1075  //
  1076  // Serialize panics if b is not of sufficient size to hold all the options in s.
  1077  func (s IPv4OptionsSerializer) Serialize(b []byte) uint8 {
  1078  	var total uint8
  1079  	for _, opt := range s {
  1080  		ty := opt.optionType()
  1081  		if withPayload, ok := opt.(IPv4SerializableOptionPayload); ok {
  1082  			// Serialize first to reduce bounds checks.
  1083  			l := 2 + withPayload.serializeInto(b[2:])
  1084  			b[0] = byte(ty)
  1085  			b[1] = l
  1086  			b = b[l:]
  1087  			total += l
  1088  			continue
  1089  		}
  1090  		// Options without payload consist only of the type field.
  1091  		//
  1092  		// NB: Repeating code from the branch above is intentional to minimize
  1093  		// bounds checks.
  1094  		b[0] = byte(ty)
  1095  		b = b[1:]
  1096  		total++
  1097  	}
  1098  
  1099  	// According to RFC 791:
  1100  	//
  1101  	//  The internet header padding is used to ensure that the internet
  1102  	//  header ends on a 32 bit boundary. The padding is zero.
  1103  	padded := padIPv4OptionsLength(total)
  1104  	b = b[:padded-total]
  1105  	for i := range b {
  1106  		b[i] = 0
  1107  	}
  1108  	return padded
  1109  }
  1110  
  1111  var _ IPv4SerializableOptionPayload = (*IPv4SerializableRouterAlertOption)(nil)
  1112  var _ IPv4SerializableOption = (*IPv4SerializableRouterAlertOption)(nil)
  1113  
  1114  // IPv4SerializableRouterAlertOption provides serialization of the Router Alert
  1115  // IPv4 option according to RFC 2113.
  1116  type IPv4SerializableRouterAlertOption struct{}
  1117  
  1118  // Type implements IPv4SerializableOption.
  1119  func (*IPv4SerializableRouterAlertOption) optionType() IPv4OptionType {
  1120  	return IPv4OptionRouterAlertType
  1121  }
  1122  
  1123  // Length implements IPv4SerializableOption.
  1124  func (*IPv4SerializableRouterAlertOption) length() uint8 {
  1125  	return IPv4OptionRouterAlertLength - IPv4OptionRouterAlertValueOffset
  1126  }
  1127  
  1128  // SerializeInto implements IPv4SerializableOption.
  1129  func (o *IPv4SerializableRouterAlertOption) serializeInto(buffer []byte) uint8 {
  1130  	binary.BigEndian.PutUint16(buffer, IPv4OptionRouterAlertValue)
  1131  	return o.length()
  1132  }
  1133  
  1134  var _ IPv4SerializableOption = (*IPv4SerializableNOPOption)(nil)
  1135  
  1136  // IPv4SerializableNOPOption provides serialization for the IPv4 no-op option.
  1137  type IPv4SerializableNOPOption struct{}
  1138  
  1139  // Type implements IPv4SerializableOption.
  1140  func (*IPv4SerializableNOPOption) optionType() IPv4OptionType {
  1141  	return IPv4OptionNOPType
  1142  }
  1143  
  1144  var _ IPv4SerializableOption = (*IPv4SerializableListEndOption)(nil)
  1145  
  1146  // IPv4SerializableListEndOption provides serialization for the IPv4 List End
  1147  // option.
  1148  type IPv4SerializableListEndOption struct{}
  1149  
  1150  // Type implements IPv4SerializableOption.
  1151  func (*IPv4SerializableListEndOption) optionType() IPv4OptionType {
  1152  	return IPv4OptionListEndType
  1153  }