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