github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/tcpip/network/ipv4/icmp.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 ipv4 16 17 import ( 18 "fmt" 19 20 "github.com/MerlinKodo/gvisor/pkg/buffer" 21 "github.com/MerlinKodo/gvisor/pkg/tcpip" 22 "github.com/MerlinKodo/gvisor/pkg/tcpip/checksum" 23 "github.com/MerlinKodo/gvisor/pkg/tcpip/header" 24 "github.com/MerlinKodo/gvisor/pkg/tcpip/header/parse" 25 "github.com/MerlinKodo/gvisor/pkg/tcpip/stack" 26 ) 27 28 // icmpv4DestinationUnreachableSockError is a general ICMPv4 Destination 29 // Unreachable error. 30 // 31 // +stateify savable 32 type icmpv4DestinationUnreachableSockError struct{} 33 34 // Origin implements tcpip.SockErrorCause. 35 func (*icmpv4DestinationUnreachableSockError) Origin() tcpip.SockErrOrigin { 36 return tcpip.SockExtErrorOriginICMP 37 } 38 39 // Type implements tcpip.SockErrorCause. 40 func (*icmpv4DestinationUnreachableSockError) Type() uint8 { 41 return uint8(header.ICMPv4DstUnreachable) 42 } 43 44 // Info implements tcpip.SockErrorCause. 45 func (*icmpv4DestinationUnreachableSockError) Info() uint32 { 46 return 0 47 } 48 49 var _ stack.TransportError = (*icmpv4DestinationHostUnreachableSockError)(nil) 50 51 // icmpv4DestinationHostUnreachableSockError is an ICMPv4 Destination Host 52 // Unreachable error. 53 // 54 // It indicates that a packet was not able to reach the destination host. 55 // 56 // +stateify savable 57 type icmpv4DestinationHostUnreachableSockError struct { 58 icmpv4DestinationUnreachableSockError 59 } 60 61 // Code implements tcpip.SockErrorCause. 62 func (*icmpv4DestinationHostUnreachableSockError) Code() uint8 { 63 return uint8(header.ICMPv4HostUnreachable) 64 } 65 66 // Kind implements stack.TransportError. 67 func (*icmpv4DestinationHostUnreachableSockError) Kind() stack.TransportErrorKind { 68 return stack.DestinationHostUnreachableTransportError 69 } 70 71 var _ stack.TransportError = (*icmpv4DestinationNetUnreachableSockError)(nil) 72 73 // icmpv4DestinationNetUnreachableSockError is an ICMPv4 Destination Net 74 // Unreachable error. 75 // 76 // It indicates that a packet was not able to reach the destination network. 77 // 78 // +stateify savable 79 type icmpv4DestinationNetUnreachableSockError struct { 80 icmpv4DestinationUnreachableSockError 81 } 82 83 // Code implements tcpip.SockErrorCause. 84 func (*icmpv4DestinationNetUnreachableSockError) Code() uint8 { 85 return uint8(header.ICMPv4NetUnreachable) 86 } 87 88 // Kind implements stack.TransportError. 89 func (*icmpv4DestinationNetUnreachableSockError) Kind() stack.TransportErrorKind { 90 return stack.DestinationNetworkUnreachableTransportError 91 } 92 93 var _ stack.TransportError = (*icmpv4DestinationPortUnreachableSockError)(nil) 94 95 // icmpv4DestinationPortUnreachableSockError is an ICMPv4 Destination Port 96 // Unreachable error. 97 // 98 // It indicates that a packet reached the destination host, but the transport 99 // protocol was not active on the destination port. 100 // 101 // +stateify savable 102 type icmpv4DestinationPortUnreachableSockError struct { 103 icmpv4DestinationUnreachableSockError 104 } 105 106 // Code implements tcpip.SockErrorCause. 107 func (*icmpv4DestinationPortUnreachableSockError) Code() uint8 { 108 return uint8(header.ICMPv4PortUnreachable) 109 } 110 111 // Kind implements stack.TransportError. 112 func (*icmpv4DestinationPortUnreachableSockError) Kind() stack.TransportErrorKind { 113 return stack.DestinationPortUnreachableTransportError 114 } 115 116 var _ stack.TransportError = (*icmpv4DestinationProtoUnreachableSockError)(nil) 117 118 // icmpv4DestinationProtoUnreachableSockError is an ICMPv4 Destination Protocol 119 // Unreachable error. 120 // 121 // It indicates that a packet reached the destination host, but the transport 122 // protocol was not reachable 123 // 124 // +stateify savable 125 type icmpv4DestinationProtoUnreachableSockError struct { 126 icmpv4DestinationUnreachableSockError 127 } 128 129 // Code implements tcpip.SockErrorCause. 130 func (*icmpv4DestinationProtoUnreachableSockError) Code() uint8 { 131 return uint8(header.ICMPv4ProtoUnreachable) 132 } 133 134 // Kind implements stack.TransportError. 135 func (*icmpv4DestinationProtoUnreachableSockError) Kind() stack.TransportErrorKind { 136 return stack.DestinationProtoUnreachableTransportError 137 } 138 139 var _ stack.TransportError = (*icmpv4SourceRouteFailedSockError)(nil) 140 141 // icmpv4SourceRouteFailedSockError is an ICMPv4 Destination Unreachable error 142 // due to source route failed. 143 // 144 // +stateify savable 145 type icmpv4SourceRouteFailedSockError struct { 146 icmpv4DestinationUnreachableSockError 147 } 148 149 // Code implements tcpip.SockErrorCause. 150 func (*icmpv4SourceRouteFailedSockError) Code() uint8 { 151 return uint8(header.ICMPv4SourceRouteFailed) 152 } 153 154 // Kind implements stack.TransportError. 155 func (*icmpv4SourceRouteFailedSockError) Kind() stack.TransportErrorKind { 156 return stack.SourceRouteFailedTransportError 157 } 158 159 var _ stack.TransportError = (*icmpv4SourceHostIsolatedSockError)(nil) 160 161 // icmpv4SourceHostIsolatedSockError is an ICMPv4 Destination Unreachable error 162 // due to source host isolated (not on the network). 163 // 164 // +stateify savable 165 type icmpv4SourceHostIsolatedSockError struct { 166 icmpv4DestinationUnreachableSockError 167 } 168 169 // Code implements tcpip.SockErrorCause. 170 func (*icmpv4SourceHostIsolatedSockError) Code() uint8 { 171 return uint8(header.ICMPv4SourceHostIsolated) 172 } 173 174 // Kind implements stack.TransportError. 175 func (*icmpv4SourceHostIsolatedSockError) Kind() stack.TransportErrorKind { 176 return stack.SourceHostIsolatedTransportError 177 } 178 179 var _ stack.TransportError = (*icmpv4DestinationHostUnknownSockError)(nil) 180 181 // icmpv4DestinationHostUnknownSockError is an ICMPv4 Destination Unreachable 182 // error due to destination host unknown/down. 183 // 184 // +stateify savable 185 type icmpv4DestinationHostUnknownSockError struct { 186 icmpv4DestinationUnreachableSockError 187 } 188 189 // Code implements tcpip.SockErrorCause. 190 func (*icmpv4DestinationHostUnknownSockError) Code() uint8 { 191 return uint8(header.ICMPv4DestinationHostUnknown) 192 } 193 194 // Kind implements stack.TransportError. 195 func (*icmpv4DestinationHostUnknownSockError) Kind() stack.TransportErrorKind { 196 return stack.DestinationHostDownTransportError 197 } 198 199 var _ stack.TransportError = (*icmpv4FragmentationNeededSockError)(nil) 200 201 // icmpv4FragmentationNeededSockError is an ICMPv4 Destination Unreachable error 202 // due to fragmentation being required but the packet was set to not be 203 // fragmented. 204 // 205 // It indicates that a link exists on the path to the destination with an MTU 206 // that is too small to carry the packet. 207 // 208 // +stateify savable 209 type icmpv4FragmentationNeededSockError struct { 210 icmpv4DestinationUnreachableSockError 211 212 mtu uint32 213 } 214 215 // Code implements tcpip.SockErrorCause. 216 func (*icmpv4FragmentationNeededSockError) Code() uint8 { 217 return uint8(header.ICMPv4FragmentationNeeded) 218 } 219 220 // Info implements tcpip.SockErrorCause. 221 func (e *icmpv4FragmentationNeededSockError) Info() uint32 { 222 return e.mtu 223 } 224 225 // Kind implements stack.TransportError. 226 func (*icmpv4FragmentationNeededSockError) Kind() stack.TransportErrorKind { 227 return stack.PacketTooBigTransportError 228 } 229 230 func (e *endpoint) checkLocalAddress(addr tcpip.Address) bool { 231 if e.nic.Spoofing() { 232 return true 233 } 234 235 if addressEndpoint := e.AcquireAssignedAddress(addr, false, stack.NeverPrimaryEndpoint); addressEndpoint != nil { 236 addressEndpoint.DecRef() 237 return true 238 } 239 return false 240 } 241 242 // handleControl handles the case when an ICMP error packet contains the headers 243 // of the original packet that caused the ICMP one to be sent. This information 244 // is used to find out which transport endpoint must be notified about the ICMP 245 // packet. We only expect the payload, not the enclosing ICMP packet. 246 func (e *endpoint) handleControl(errInfo stack.TransportError, pkt stack.PacketBufferPtr) { 247 h, ok := pkt.Data().PullUp(header.IPv4MinimumSize) 248 if !ok { 249 return 250 } 251 hdr := header.IPv4(h) 252 253 // We don't use IsValid() here because ICMP only requires that the IP 254 // header plus 8 bytes of the transport header be included. So it's 255 // likely that it is truncated, which would cause IsValid to return 256 // false. 257 // 258 // Drop packet if it doesn't have the basic IPv4 header or if the 259 // original source address doesn't match an address we own. 260 srcAddr := hdr.SourceAddress() 261 if !e.checkLocalAddress(srcAddr) { 262 return 263 } 264 265 hlen := int(hdr.HeaderLength()) 266 if pkt.Data().Size() < hlen || hdr.FragmentOffset() != 0 { 267 // We won't be able to handle this if it doesn't contain the 268 // full IPv4 header, or if it's a fragment not at offset 0 269 // (because it won't have the transport header). 270 return 271 } 272 273 // Keep needed information before trimming header. 274 p := hdr.TransportProtocol() 275 dstAddr := hdr.DestinationAddress() 276 // Skip the ip header, then deliver the error. 277 if _, ok := pkt.Data().Consume(hlen); !ok { 278 panic(fmt.Sprintf("could not consume the IP header of %d bytes", hlen)) 279 } 280 e.dispatcher.DeliverTransportError(srcAddr, dstAddr, ProtocolNumber, p, errInfo, pkt) 281 } 282 283 func (e *endpoint) handleICMP(pkt stack.PacketBufferPtr) { 284 received := e.stats.icmp.packetsReceived 285 h := header.ICMPv4(pkt.TransportHeader().Slice()) 286 if len(h) < header.ICMPv4MinimumSize { 287 received.invalid.Increment() 288 return 289 } 290 291 // Only do in-stack processing if the checksum is correct. 292 if checksum.Checksum(h, pkt.Data().Checksum()) != 0xffff { 293 received.invalid.Increment() 294 // It's possible that a raw socket expects to receive this regardless 295 // of checksum errors. If it's an echo request we know it's safe because 296 // we are the only handler, however other types do not cope well with 297 // packets with checksum errors. 298 switch h.Type() { 299 case header.ICMPv4Echo: 300 e.dispatcher.DeliverTransportPacket(header.ICMPv4ProtocolNumber, pkt) 301 } 302 return 303 } 304 305 iph := header.IPv4(pkt.NetworkHeader().Slice()) 306 var newOptions header.IPv4Options 307 if opts := iph.Options(); len(opts) != 0 { 308 // RFC 1122 section 3.2.2.6 (page 43) (and similar for other round trip 309 // type ICMP packets): 310 // If a Record Route and/or Time Stamp option is received in an 311 // ICMP Echo Request, this option (these options) SHOULD be 312 // updated to include the current host and included in the IP 313 // header of the Echo Reply message, without "truncation". 314 // Thus, the recorded route will be for the entire round trip. 315 // 316 // So we need to let the option processor know how it should handle them. 317 var op optionsUsage 318 if h.Type() == header.ICMPv4Echo { 319 op = &optionUsageEcho{} 320 } else { 321 op = &optionUsageReceive{} 322 } 323 var optProblem *header.IPv4OptParameterProblem 324 newOptions, _, optProblem = e.processIPOptions(pkt, opts, op) 325 if optProblem != nil { 326 if optProblem.NeedICMP { 327 _ = e.protocol.returnError(&icmpReasonParamProblem{ 328 pointer: optProblem.Pointer, 329 }, pkt, true /* deliveredLocally */) 330 e.stats.ip.MalformedPacketsReceived.Increment() 331 } 332 return 333 } 334 copied := copy(opts, newOptions) 335 if copied != len(newOptions) { 336 panic(fmt.Sprintf("copied %d bytes of new options, expected %d bytes", copied, len(newOptions))) 337 } 338 for i := copied; i < len(opts); i++ { 339 // Pad with 0 (EOL). RFC 791 page 23 says "The padding is zero". 340 opts[i] = byte(header.IPv4OptionListEndType) 341 } 342 } 343 344 // TODO(b/112892170): Meaningfully handle all ICMP types. 345 switch h.Type() { 346 case header.ICMPv4Echo: 347 received.echoRequest.Increment() 348 349 // DeliverTransportPacket may modify pkt so don't use it beyond 350 // this point. Make a deep copy of the data before pkt gets sent as we will 351 // be modifying fields. Both the ICMP header (with its type modified to 352 // EchoReply) and payload are reused in the reply packet. 353 // 354 // TODO(gvisor.dev/issue/4399): The copy may not be needed if there are no 355 // waiting endpoints. Consider moving responsibility for doing the copy to 356 // DeliverTransportPacket so that is is only done when needed. 357 replyData := stack.PayloadSince(pkt.TransportHeader()) 358 defer replyData.Release() 359 ipHdr := header.IPv4(pkt.NetworkHeader().Slice()) 360 localAddressBroadcast := pkt.NetworkPacketInfo.LocalAddressBroadcast 361 362 // It's possible that a raw socket expects to receive this. 363 e.dispatcher.DeliverTransportPacket(header.ICMPv4ProtocolNumber, pkt) 364 pkt = nil 365 366 sent := e.stats.icmp.packetsSent 367 if !e.protocol.allowICMPReply(header.ICMPv4EchoReply, header.ICMPv4UnusedCode) { 368 sent.rateLimited.Increment() 369 return 370 } 371 372 // As per RFC 1122 section 3.2.1.3, when a host sends any datagram, the IP 373 // source address MUST be one of its own IP addresses (but not a broadcast 374 // or multicast address). 375 localAddr := ipHdr.DestinationAddress() 376 if localAddressBroadcast || header.IsV4MulticastAddress(localAddr) { 377 localAddr = tcpip.Address{} 378 } 379 380 r, err := e.protocol.stack.FindRoute(e.nic.ID(), localAddr, ipHdr.SourceAddress(), ProtocolNumber, false /* multicastLoop */) 381 if err != nil { 382 // If we cannot find a route to the destination, silently drop the packet. 383 return 384 } 385 defer r.Release() 386 387 outgoingEP, ok := e.protocol.getEndpointForNIC(r.NICID()) 388 if !ok { 389 // The outgoing NIC went away. 390 sent.dropped.Increment() 391 return 392 } 393 394 // Because IP and ICMP are so closely intertwined, we need to handcraft our 395 // IP header to be able to follow RFC 792. The wording on page 13 is as 396 // follows: 397 // IP Fields: 398 // Addresses 399 // The address of the source in an echo message will be the 400 // destination of the echo reply message. To form an echo reply 401 // message, the source and destination addresses are simply reversed, 402 // the type code changed to 0, and the checksum recomputed. 403 // 404 // This was interpreted by early implementors to mean that all options must 405 // be copied from the echo request IP header to the echo reply IP header 406 // and this behaviour is still relied upon by some applications. 407 // 408 // Create a copy of the IP header we received, options and all, and change 409 // The fields we need to alter. 410 // 411 // We need to produce the entire packet in the data segment in order to 412 // use WriteHeaderIncludedPacket(). WriteHeaderIncludedPacket sets the 413 // total length and the header checksum so we don't need to set those here. 414 // 415 // Take the base of the incoming request IP header but replace the options. 416 replyHeaderLength := uint8(header.IPv4MinimumSize + len(newOptions)) 417 replyIPHdrView := buffer.NewView(int(replyHeaderLength)) 418 replyIPHdrView.Write(iph[:header.IPv4MinimumSize]) 419 replyIPHdrView.Write(newOptions) 420 replyIPHdr := header.IPv4(replyIPHdrView.AsSlice()) 421 replyIPHdr.SetHeaderLength(replyHeaderLength) 422 replyIPHdr.SetSourceAddress(r.LocalAddress()) 423 replyIPHdr.SetDestinationAddress(r.RemoteAddress()) 424 replyIPHdr.SetTTL(r.DefaultTTL()) 425 replyIPHdr.SetTotalLength(uint16(len(replyIPHdr) + len(replyData.AsSlice()))) 426 replyIPHdr.SetChecksum(0) 427 replyIPHdr.SetChecksum(^replyIPHdr.CalculateChecksum()) 428 429 replyICMPHdr := header.ICMPv4(replyData.AsSlice()) 430 replyICMPHdr.SetType(header.ICMPv4EchoReply) 431 replyICMPHdr.SetChecksum(0) 432 replyICMPHdr.SetChecksum(^checksum.Checksum(replyData.AsSlice(), 0)) 433 434 replyBuf := buffer.MakeWithView(replyIPHdrView) 435 replyBuf.Append(replyData.Clone()) 436 replyPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 437 ReserveHeaderBytes: int(r.MaxHeaderLength()), 438 Payload: replyBuf, 439 }) 440 defer replyPkt.DecRef() 441 // Populate the network/transport headers in the packet buffer so the 442 // ICMP packet goes through IPTables. 443 if ok := parse.IPv4(replyPkt); !ok { 444 panic("expected to parse IPv4 header we just created") 445 } 446 if ok := parse.ICMPv4(replyPkt); !ok { 447 panic("expected to parse ICMPv4 header we just created") 448 } 449 450 if err := outgoingEP.writePacket(r, replyPkt); err != nil { 451 sent.dropped.Increment() 452 return 453 } 454 sent.echoReply.Increment() 455 456 case header.ICMPv4EchoReply: 457 received.echoReply.Increment() 458 459 // ICMP sockets expect the ICMP header to be present, so we don't consume 460 // the ICMP header. 461 e.dispatcher.DeliverTransportPacket(header.ICMPv4ProtocolNumber, pkt) 462 463 case header.ICMPv4DstUnreachable: 464 received.dstUnreachable.Increment() 465 466 mtu := h.MTU() 467 code := h.Code() 468 switch code { 469 case header.ICMPv4NetUnreachable, 470 header.ICMPv4DestinationNetworkUnknown, 471 header.ICMPv4NetUnreachableForTos, 472 header.ICMPv4NetProhibited: 473 e.handleControl(&icmpv4DestinationNetUnreachableSockError{}, pkt) 474 case header.ICMPv4HostUnreachable, 475 header.ICMPv4HostProhibited, 476 header.ICMPv4AdminProhibited, 477 header.ICMPv4HostUnreachableForTos, 478 header.ICMPv4HostPrecedenceViolation, 479 header.ICMPv4PrecedenceCutInEffect: 480 e.handleControl(&icmpv4DestinationHostUnreachableSockError{}, pkt) 481 case header.ICMPv4PortUnreachable: 482 e.handleControl(&icmpv4DestinationPortUnreachableSockError{}, pkt) 483 case header.ICMPv4FragmentationNeeded: 484 networkMTU, err := calculateNetworkMTU(uint32(mtu), header.IPv4MinimumSize) 485 if err != nil { 486 networkMTU = 0 487 } 488 e.handleControl(&icmpv4FragmentationNeededSockError{mtu: networkMTU}, pkt) 489 case header.ICMPv4ProtoUnreachable: 490 e.handleControl(&icmpv4DestinationProtoUnreachableSockError{}, pkt) 491 case header.ICMPv4SourceRouteFailed: 492 e.handleControl(&icmpv4SourceRouteFailedSockError{}, pkt) 493 case header.ICMPv4SourceHostIsolated: 494 e.handleControl(&icmpv4SourceHostIsolatedSockError{}, pkt) 495 case header.ICMPv4DestinationHostUnknown: 496 e.handleControl(&icmpv4DestinationHostUnknownSockError{}, pkt) 497 } 498 case header.ICMPv4SrcQuench: 499 received.srcQuench.Increment() 500 501 case header.ICMPv4Redirect: 502 received.redirect.Increment() 503 504 case header.ICMPv4TimeExceeded: 505 received.timeExceeded.Increment() 506 507 case header.ICMPv4ParamProblem: 508 received.paramProblem.Increment() 509 510 case header.ICMPv4Timestamp: 511 received.timestamp.Increment() 512 513 case header.ICMPv4TimestampReply: 514 received.timestampReply.Increment() 515 516 case header.ICMPv4InfoRequest: 517 received.infoRequest.Increment() 518 519 case header.ICMPv4InfoReply: 520 received.infoReply.Increment() 521 522 default: 523 received.invalid.Increment() 524 } 525 } 526 527 // ======= ICMP Error packet generation ========= 528 529 // icmpReason is a marker interface for IPv4 specific ICMP errors. 530 type icmpReason interface { 531 isICMPReason() 532 } 533 534 // icmpReasonNetworkProhibited is an error where the destination network is 535 // prohibited. 536 type icmpReasonNetworkProhibited struct{} 537 538 func (*icmpReasonNetworkProhibited) isICMPReason() {} 539 540 // icmpReasonHostProhibited is an error where the destination host is 541 // prohibited. 542 type icmpReasonHostProhibited struct{} 543 544 func (*icmpReasonHostProhibited) isICMPReason() {} 545 546 // icmpReasonAdministrativelyProhibited is an error where the destination is 547 // administratively prohibited. 548 type icmpReasonAdministrativelyProhibited struct{} 549 550 func (*icmpReasonAdministrativelyProhibited) isICMPReason() {} 551 552 // icmpReasonPortUnreachable is an error where the transport protocol has no 553 // listener and no alternative means to inform the sender. 554 type icmpReasonPortUnreachable struct{} 555 556 func (*icmpReasonPortUnreachable) isICMPReason() {} 557 558 // icmpReasonProtoUnreachable is an error where the transport protocol is 559 // not supported. 560 type icmpReasonProtoUnreachable struct{} 561 562 func (*icmpReasonProtoUnreachable) isICMPReason() {} 563 564 // icmpReasonTTLExceeded is an error where a packet's time to live exceeded in 565 // transit to its final destination, as per RFC 792 page 6, Time Exceeded 566 // Message. 567 type icmpReasonTTLExceeded struct{} 568 569 func (*icmpReasonTTLExceeded) isICMPReason() {} 570 571 // icmpReasonReassemblyTimeout is an error where insufficient fragments are 572 // received to complete reassembly of a packet within a configured time after 573 // the reception of the first-arriving fragment of that packet. 574 type icmpReasonReassemblyTimeout struct{} 575 576 func (*icmpReasonReassemblyTimeout) isICMPReason() {} 577 578 // icmpReasonParamProblem is an error to use to request a Parameter Problem 579 // message to be sent. 580 type icmpReasonParamProblem struct { 581 pointer byte 582 } 583 584 func (*icmpReasonParamProblem) isICMPReason() {} 585 586 // icmpReasonNetworkUnreachable is an error in which the network specified in 587 // the internet destination field of the datagram is unreachable. 588 type icmpReasonNetworkUnreachable struct{} 589 590 func (*icmpReasonNetworkUnreachable) isICMPReason() {} 591 592 // icmpReasonFragmentationNeeded is an error where a packet requires 593 // fragmentation while also having the Don't Fragment flag set, as per RFC 792 594 // page 3, Destination Unreachable Message. 595 type icmpReasonFragmentationNeeded struct{} 596 597 func (*icmpReasonFragmentationNeeded) isICMPReason() {} 598 599 // icmpReasonHostUnreachable is an error in which the host specified in the 600 // internet destination field of the datagram is unreachable. 601 type icmpReasonHostUnreachable struct{} 602 603 func (*icmpReasonHostUnreachable) isICMPReason() {} 604 605 // returnError takes an error descriptor and generates the appropriate ICMP 606 // error packet for IPv4 and sends it back to the remote device that sent 607 // the problematic packet. It incorporates as much of that packet as 608 // possible as well as any error metadata as is available. returnError 609 // expects pkt to hold a valid IPv4 packet as per the wire format. 610 func (p *protocol) returnError(reason icmpReason, pkt stack.PacketBufferPtr, deliveredLocally bool) tcpip.Error { 611 origIPHdr := header.IPv4(pkt.NetworkHeader().Slice()) 612 origIPHdrSrc := origIPHdr.SourceAddress() 613 origIPHdrDst := origIPHdr.DestinationAddress() 614 615 // We check we are responding only when we are allowed to. 616 // See RFC 1812 section 4.3.2.7 (shown below). 617 // 618 // ========= 619 // 4.3.2.7 When Not to Send ICMP Errors 620 // 621 // An ICMP error message MUST NOT be sent as the result of receiving: 622 // 623 // o An ICMP error message, or 624 // 625 // o A packet which fails the IP header validation tests described in 626 // Section [5.2.2] (except where that section specifically permits 627 // the sending of an ICMP error message), or 628 // 629 // o A packet destined to an IP broadcast or IP multicast address, or 630 // 631 // o A packet sent as a Link Layer broadcast or multicast, or 632 // 633 // o Any fragment of a datagram other then the first fragment (i.e., a 634 // packet for which the fragment offset in the IP header is nonzero). 635 // 636 // TODO(gvisor.dev/issues/4058): Make sure we don't send ICMP errors in 637 // response to a non-initial fragment, but it currently can not happen. 638 if pkt.NetworkPacketInfo.LocalAddressBroadcast || header.IsV4MulticastAddress(origIPHdrDst) || origIPHdrSrc == header.IPv4Any { 639 return nil 640 } 641 642 // If the packet wasn't delivered locally, do not use the packet's destination 643 // address as the response's source address as we should not not own the 644 // destination address of a packet we are forwarding. 645 localAddr := origIPHdrDst 646 if !deliveredLocally { 647 localAddr = tcpip.Address{} 648 } 649 650 // Even if we were able to receive a packet from some remote, we may not have 651 // a route to it - the remote may be blocked via routing rules. We must always 652 // consult our routing table and find a route to the remote before sending any 653 // packet. 654 route, err := p.stack.FindRoute(pkt.NICID, localAddr, origIPHdrSrc, ProtocolNumber, false /* multicastLoop */) 655 if err != nil { 656 return err 657 } 658 defer route.Release() 659 660 p.mu.Lock() 661 // We retrieve an endpoint using the newly constructed route's NICID rather 662 // than the packet's NICID. The packet's NICID corresponds to the NIC on 663 // which it arrived, which isn't necessarily the same as the NIC on which it 664 // will be transmitted. On the other hand, the route's NIC *is* guaranteed 665 // to be the NIC on which the packet will be transmitted. 666 netEP, ok := p.eps[route.NICID()] 667 p.mu.Unlock() 668 if !ok { 669 return &tcpip.ErrNotConnected{} 670 } 671 672 transportHeader := pkt.TransportHeader().Slice() 673 674 // Don't respond to icmp error packets. 675 if origIPHdr.Protocol() == uint8(header.ICMPv4ProtocolNumber) { 676 // We need to decide to explicitly name the packets we can respond to or 677 // the ones we can not respond to. The decision is somewhat arbitrary and 678 // if problems arise this could be reversed. It was judged less of a breach 679 // of protocol to not respond to unknown non-error packets than to respond 680 // to unknown error packets so we take the first approach. 681 if len(transportHeader) < header.ICMPv4MinimumSize { 682 // The packet is malformed. 683 return nil 684 } 685 switch header.ICMPv4(transportHeader).Type() { 686 case 687 header.ICMPv4EchoReply, 688 header.ICMPv4Echo, 689 header.ICMPv4Timestamp, 690 header.ICMPv4TimestampReply, 691 header.ICMPv4InfoRequest, 692 header.ICMPv4InfoReply: 693 default: 694 // Assume any type we don't know about may be an error type. 695 return nil 696 } 697 } 698 699 sent := netEP.stats.icmp.packetsSent 700 icmpType, icmpCode, counter, pointer := func() (header.ICMPv4Type, header.ICMPv4Code, tcpip.MultiCounterStat, byte) { 701 switch reason := reason.(type) { 702 case *icmpReasonNetworkProhibited: 703 return header.ICMPv4DstUnreachable, header.ICMPv4NetProhibited, sent.dstUnreachable, 0 704 case *icmpReasonHostProhibited: 705 return header.ICMPv4DstUnreachable, header.ICMPv4HostProhibited, sent.dstUnreachable, 0 706 case *icmpReasonAdministrativelyProhibited: 707 return header.ICMPv4DstUnreachable, header.ICMPv4AdminProhibited, sent.dstUnreachable, 0 708 case *icmpReasonPortUnreachable: 709 return header.ICMPv4DstUnreachable, header.ICMPv4PortUnreachable, sent.dstUnreachable, 0 710 case *icmpReasonProtoUnreachable: 711 return header.ICMPv4DstUnreachable, header.ICMPv4ProtoUnreachable, sent.dstUnreachable, 0 712 case *icmpReasonNetworkUnreachable: 713 return header.ICMPv4DstUnreachable, header.ICMPv4NetUnreachable, sent.dstUnreachable, 0 714 case *icmpReasonHostUnreachable: 715 return header.ICMPv4DstUnreachable, header.ICMPv4HostUnreachable, sent.dstUnreachable, 0 716 case *icmpReasonFragmentationNeeded: 717 return header.ICMPv4DstUnreachable, header.ICMPv4FragmentationNeeded, sent.dstUnreachable, 0 718 case *icmpReasonTTLExceeded: 719 return header.ICMPv4TimeExceeded, header.ICMPv4TTLExceeded, sent.timeExceeded, 0 720 case *icmpReasonReassemblyTimeout: 721 return header.ICMPv4TimeExceeded, header.ICMPv4ReassemblyTimeout, sent.timeExceeded, 0 722 case *icmpReasonParamProblem: 723 return header.ICMPv4ParamProblem, header.ICMPv4UnusedCode, sent.paramProblem, reason.pointer 724 default: 725 panic(fmt.Sprintf("unsupported ICMP type %T", reason)) 726 } 727 }() 728 729 if !p.allowICMPReply(icmpType, icmpCode) { 730 sent.rateLimited.Increment() 731 return nil 732 } 733 734 // Now work out how much of the triggering packet we should return. 735 // As per RFC 1812 Section 4.3.2.3 736 // 737 // ICMP datagram SHOULD contain as much of the original 738 // datagram as possible without the length of the ICMP 739 // datagram exceeding 576 bytes. 740 // 741 // NOTE: The above RFC referenced is different from the original 742 // recommendation in RFC 1122 and RFC 792 where it mentioned that at 743 // least 8 bytes of the payload must be included. Today linux and other 744 // systems implement the RFC 1812 definition and not the original 745 // requirement. We treat 8 bytes as the minimum but will try send more. 746 mtu := int(route.MTU()) 747 const maxIPData = header.IPv4MinimumProcessableDatagramSize - header.IPv4MinimumSize 748 if mtu > maxIPData { 749 mtu = maxIPData 750 } 751 available := mtu - header.ICMPv4MinimumSize 752 753 if available < len(origIPHdr)+header.ICMPv4MinimumErrorPayloadSize { 754 return nil 755 } 756 757 payloadLen := len(origIPHdr) + len(transportHeader) + pkt.Data().Size() 758 if payloadLen > available { 759 payloadLen = available 760 } 761 762 // The buffers used by pkt may be used elsewhere in the system. 763 // For example, an AF_RAW or AF_PACKET socket may use what the transport 764 // protocol considers an unreachable destination. Thus we deep copy pkt to 765 // prevent multiple ownership and SR errors. The new copy is a vectorized 766 // view with the entire incoming IP packet reassembled and truncated as 767 // required. This is now the payload of the new ICMP packet and no longer 768 // considered a packet in its own right. 769 770 payload := buffer.MakeWithView(pkt.NetworkHeader().View()) 771 payload.Append(pkt.TransportHeader().View()) 772 if dataCap := payloadLen - int(payload.Size()); dataCap > 0 { 773 buf := pkt.Data().ToBuffer() 774 buf.Truncate(int64(dataCap)) 775 payload.Merge(&buf) 776 } else { 777 payload.Truncate(int64(payloadLen)) 778 } 779 780 icmpPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 781 ReserveHeaderBytes: int(route.MaxHeaderLength()) + header.ICMPv4MinimumSize, 782 Payload: payload, 783 }) 784 defer icmpPkt.DecRef() 785 786 icmpPkt.TransportProtocolNumber = header.ICMPv4ProtocolNumber 787 788 icmpHdr := header.ICMPv4(icmpPkt.TransportHeader().Push(header.ICMPv4MinimumSize)) 789 icmpHdr.SetCode(icmpCode) 790 icmpHdr.SetType(icmpType) 791 icmpHdr.SetPointer(pointer) 792 icmpHdr.SetChecksum(header.ICMPv4Checksum(icmpHdr, icmpPkt.Data().Checksum())) 793 794 if err := route.WritePacket( 795 stack.NetworkHeaderParams{ 796 Protocol: header.ICMPv4ProtocolNumber, 797 TTL: route.DefaultTTL(), 798 TOS: stack.DefaultTOS, 799 }, 800 icmpPkt, 801 ); err != nil { 802 sent.dropped.Increment() 803 return err 804 } 805 counter.Increment() 806 return nil 807 } 808 809 // OnReassemblyTimeout implements fragmentation.TimeoutHandler. 810 func (p *protocol) OnReassemblyTimeout(pkt stack.PacketBufferPtr) { 811 // OnReassemblyTimeout sends a Time Exceeded Message, as per RFC 792: 812 // 813 // If a host reassembling a fragmented datagram cannot complete the 814 // reassembly due to missing fragments within its time limit it discards the 815 // datagram, and it may send a time exceeded message. 816 // 817 // If fragment zero is not available then no time exceeded need be sent at 818 // all. 819 if !pkt.IsNil() { 820 p.returnError(&icmpReasonReassemblyTimeout{}, pkt, true /* deliveredLocally */) 821 } 822 }