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