github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/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/metacubex/gvisor/pkg/buffer"
    21  	"github.com/metacubex/gvisor/pkg/tcpip"
    22  	"github.com/metacubex/gvisor/pkg/tcpip/checksum"
    23  	"github.com/metacubex/gvisor/pkg/tcpip/header"
    24  	"github.com/metacubex/gvisor/pkg/tcpip/header/parse"
    25  	"github.com/metacubex/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.PacketBuffer) {
   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.PacketBuffer) {
   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.PacketBuffer, 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.PacketBuffer) {
   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  }