ipv4.go raw

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