// Copyright 2018 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ipv6

import (
	"github.com/google/netstack/tcpip"
	"github.com/google/netstack/tcpip/buffer"
	"github.com/google/netstack/tcpip/header"
	"github.com/google/netstack/tcpip/stack"
)

// handleControl handles the case when an ICMP packet contains the headers of
// the original packet that caused the ICMP one to be sent. This information is
// used to find out which transport endpoint must be notified about the ICMP
// packet.
func (e *endpoint) handleControl(typ stack.ControlType, extra uint32, vv buffer.VectorisedView) {
	h := header.IPv6(vv.First())

	// We don't use IsValid() here because ICMP only requires that up to
	// 1280 bytes of the original packet be included. So it's likely that it
	// is truncated, which would cause IsValid to return false.
	//
	// Drop packet if it doesn't have the basic IPv6 header or if the
	// original source address doesn't match the endpoint's address.
	if len(h) < header.IPv6MinimumSize || h.SourceAddress() != e.id.LocalAddress {
		return
	}

	// Skip the IP header, then handle the fragmentation header if there
	// is one.
	vv.TrimFront(header.IPv6MinimumSize)
	p := h.TransportProtocol()
	if p == header.IPv6FragmentHeader {
		f := header.IPv6Fragment(vv.First())
		if !f.IsValid() || f.FragmentOffset() != 0 {
			// We can't handle fragments that aren't at offset 0
			// because they don't have the transport headers.
			return
		}

		// Skip fragmentation header and find out the actual protocol
		// number.
		vv.TrimFront(header.IPv6FragmentHeaderSize)
		p = f.TransportProtocol()
	}

	// Deliver the control packet to the transport endpoint.
	e.dispatcher.DeliverTransportControlPacket(e.id.LocalAddress, h.DestinationAddress(), ProtocolNumber, p, typ, extra, vv)
}

func (e *endpoint) handleICMP(r *stack.Route, netHeader buffer.View, vv buffer.VectorisedView) {
	stats := r.Stats().ICMP
	sent := stats.V6PacketsSent
	received := stats.V6PacketsReceived
	v := vv.First()
	if len(v) < header.ICMPv6MinimumSize {
		received.Invalid.Increment()
		return
	}
	h := header.ICMPv6(v)
	iph := header.IPv6(netHeader)

	// As per RFC 4861 sections 4.1 - 4.5, 6.1.1, 6.1.2, 7.1.1, 7.1.2 and
	// 8.1, nodes MUST silently drop NDP packets where the Hop Limit field
	// in the IPv6 header is not set to 255.
	switch h.Type() {
	case header.ICMPv6NeighborSolicit,
		header.ICMPv6NeighborAdvert,
		header.ICMPv6RouterSolicit,
		header.ICMPv6RouterAdvert,
		header.ICMPv6RedirectMsg:
		if iph.HopLimit() != header.NDPHopLimit {
			received.Invalid.Increment()
			return
		}
	}

	// TODO(b/112892170): Meaningfully handle all ICMP types.
	switch h.Type() {
	case header.ICMPv6PacketTooBig:
		received.PacketTooBig.Increment()
		if len(v) < header.ICMPv6PacketTooBigMinimumSize {
			received.Invalid.Increment()
			return
		}
		vv.TrimFront(header.ICMPv6PacketTooBigMinimumSize)
		mtu := h.MTU()
		e.handleControl(stack.ControlPacketTooBig, calculateMTU(mtu), vv)

	case header.ICMPv6DstUnreachable:
		received.DstUnreachable.Increment()
		if len(v) < header.ICMPv6DstUnreachableMinimumSize {
			received.Invalid.Increment()
			return
		}
		vv.TrimFront(header.ICMPv6DstUnreachableMinimumSize)
		switch h.Code() {
		case header.ICMPv6PortUnreachable:
			e.handleControl(stack.ControlPortUnreachable, 0, vv)
		}

	case header.ICMPv6NeighborSolicit:
		received.NeighborSolicit.Increment()
		if len(v) < header.ICMPv6NeighborSolicitMinimumSize {
			received.Invalid.Increment()
			return
		}

		ns := header.NDPNeighborSolicit(h.NDPPayload())
		targetAddr := ns.TargetAddress()
		s := r.Stack()
		rxNICID := r.NICID()

		isTentative, err := s.IsAddrTentative(rxNICID, targetAddr)
		if err != nil {
			// We will only get an error if rxNICID is unrecognized,
			// which should not happen. For now short-circuit this
			// packet.
			//
			// TODO(b/141002840): Handle this better?
			return
		}

		if isTentative {
			// If the target address is tentative and the source
			// of the packet is a unicast (specified) address, then
			// the source of the packet is attempting to perform
			// address resolution on the target. In this case, the
			// solicitation is silently ignored, as per RFC 4862
			// section 5.4.3.
			//
			// If the target address is tentative and the source of
			// the packet is the unspecified address (::), then we
			// know another node is also performing DAD for the
			// same address (since targetAddr is tentative for us,
			// we know we are also performing DAD on it). In this
			// case we let the stack know so it can handle such a
			// scenario and do nothing further with the NDP NS.
			if iph.SourceAddress() == header.IPv6Any {
				s.DupTentativeAddrDetected(rxNICID, targetAddr)
			}

			// Do not handle neighbor solicitations targeted
			// to an address that is tentative on the received
			// NIC any further.
			return
		}

		// At this point we know that targetAddr is not tentative on
		// rxNICID so the packet is processed as defined in RFC 4861,
		// as per RFC 4862 section 5.4.3.

		if e.linkAddrCache.CheckLocalAddress(e.nicid, ProtocolNumber, targetAddr) == 0 {
			// We don't have a useful answer; the best we can do is ignore the request.
			return
		}

		optsSerializer := header.NDPOptionsSerializer{
			header.NDPTargetLinkLayerAddressOption(r.LocalLinkAddress[:]),
		}
		hdr := buffer.NewPrependable(int(r.MaxHeaderLength()) + header.ICMPv6NeighborAdvertMinimumSize + int(optsSerializer.Length()))
		pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6NeighborAdvertSize))
		pkt.SetType(header.ICMPv6NeighborAdvert)
		na := header.NDPNeighborAdvert(pkt.NDPPayload())
		na.SetSolicitedFlag(true)
		na.SetOverrideFlag(true)
		na.SetTargetAddress(targetAddr)
		opts := na.Options()
		opts.Serialize(optsSerializer)

		// ICMPv6 Neighbor Solicit messages are always sent to
		// specially crafted IPv6 multicast addresses. As a result, the
		// route we end up with here has as its LocalAddress such a
		// multicast address. It would be nonsense to claim that our
		// source address is a multicast address, so we manually set
		// the source address to the target address requested in the
		// solicit message. Since that requires mutating the route, we
		// must first clone it.
		r := r.Clone()
		defer r.Release()
		r.LocalAddress = targetAddr
		pkt.SetChecksum(header.ICMPv6Checksum(pkt, r.LocalAddress, r.RemoteAddress, buffer.VectorisedView{}))

		// TODO(tamird/ghanan): there exists an explicit NDP option that is
		// used to update the neighbor table with link addresses for a
		// neighbor from an NS (see the Source Link Layer option RFC
		// 4861 section 4.6.1 and section 7.2.3).
		//
		// Furthermore, the entirety of NDP handling here seems to be
		// contradicted by RFC 4861.
		e.linkAddrCache.AddLinkAddress(e.nicid, r.RemoteAddress, r.RemoteLinkAddress)

		// RFC 4861 Neighbor Discovery for IP version 6 (IPv6)
		//
		// 7.1.2. Validation of Neighbor Advertisements
		//
		// The IP Hop Limit field has a value of 255, i.e., the packet
		// could not possibly have been forwarded by a router.
		if err := r.WritePacket(nil /* gso */, hdr, buffer.VectorisedView{}, stack.NetworkHeaderParams{Protocol: header.ICMPv6ProtocolNumber, TTL: header.NDPHopLimit, TOS: stack.DefaultTOS}); err != nil {
			sent.Dropped.Increment()
			return
		}
		sent.NeighborAdvert.Increment()

	case header.ICMPv6NeighborAdvert:
		received.NeighborAdvert.Increment()
		if len(v) < header.ICMPv6NeighborAdvertSize {
			received.Invalid.Increment()
			return
		}

		na := header.NDPNeighborAdvert(h.NDPPayload())
		targetAddr := na.TargetAddress()
		stack := r.Stack()
		rxNICID := r.NICID()

		isTentative, err := stack.IsAddrTentative(rxNICID, targetAddr)
		if err != nil {
			// We will only get an error if rxNICID is unrecognized,
			// which should not happen. For now short-circuit this
			// packet.
			//
			// TODO(b/141002840): Handle this better?
			return
		}

		if isTentative {
			// We just got an NA from a node that owns an address we
			// are performing DAD on, implying the address is not
			// unique. In this case we let the stack know so it can
			// handle such a scenario and do nothing furthur with
			// the NDP NA.
			stack.DupTentativeAddrDetected(rxNICID, targetAddr)
			return
		}

		// At this point we know that the targetAddress is not tentaive
		// on rxNICID. However, targetAddr may still be assigned to
		// rxNICID but not tentative (it could be permanent). Such a
		// scenario is beyond the scope of RFC 4862. As such, we simply
		// ignore such a scenario for now and proceed as normal.
		//
		// TODO(b/140896005): Handle the scenario described above
		// (inform the netstack integration that a duplicate address was
		// was detected)

		e.linkAddrCache.AddLinkAddress(e.nicid, targetAddr, r.RemoteLinkAddress)
		if targetAddr != r.RemoteAddress {
			e.linkAddrCache.AddLinkAddress(e.nicid, r.RemoteAddress, r.RemoteLinkAddress)
		}

	case header.ICMPv6EchoRequest:
		received.EchoRequest.Increment()
		if len(v) < header.ICMPv6EchoMinimumSize {
			received.Invalid.Increment()
			return
		}
		vv.TrimFront(header.ICMPv6EchoMinimumSize)
		hdr := buffer.NewPrependable(int(r.MaxHeaderLength()) + header.ICMPv6EchoMinimumSize)
		pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6EchoMinimumSize))
		copy(pkt, h)
		pkt.SetType(header.ICMPv6EchoReply)
		pkt.SetChecksum(header.ICMPv6Checksum(pkt, r.LocalAddress, r.RemoteAddress, vv))
		if err := r.WritePacket(nil /* gso */, hdr, vv, stack.NetworkHeaderParams{Protocol: header.ICMPv6ProtocolNumber, TTL: r.DefaultTTL(), TOS: stack.DefaultTOS}); err != nil {
			sent.Dropped.Increment()
			return
		}
		sent.EchoReply.Increment()

	case header.ICMPv6EchoReply:
		received.EchoReply.Increment()
		if len(v) < header.ICMPv6EchoMinimumSize {
			received.Invalid.Increment()
			return
		}
		e.dispatcher.DeliverTransportPacket(r, header.ICMPv6ProtocolNumber, netHeader, vv)

	case header.ICMPv6TimeExceeded:
		received.TimeExceeded.Increment()

	case header.ICMPv6ParamProblem:
		received.ParamProblem.Increment()

	case header.ICMPv6RouterSolicit:
		received.RouterSolicit.Increment()

	case header.ICMPv6RouterAdvert:
		received.RouterAdvert.Increment()

	case header.ICMPv6RedirectMsg:
		received.RedirectMsg.Increment()

	default:
		received.Invalid.Increment()
	}
}

const (
	ndpSolicitedFlag = 1 << 6
	ndpOverrideFlag  = 1 << 5

	ndpOptSrcLinkAddr = 1
	ndpOptDstLinkAddr = 2

	icmpV6FlagOffset   = 4
	icmpV6OptOffset    = 24
	icmpV6LengthOffset = 25
)

var broadcastMAC = tcpip.LinkAddress([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff})

var _ stack.LinkAddressResolver = (*protocol)(nil)

// LinkAddressProtocol implements stack.LinkAddressResolver.
func (*protocol) LinkAddressProtocol() tcpip.NetworkProtocolNumber {
	return header.IPv6ProtocolNumber
}

// LinkAddressRequest implements stack.LinkAddressResolver.
func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, linkEP stack.LinkEndpoint) *tcpip.Error {
	snaddr := header.SolicitedNodeAddr(addr)
	r := &stack.Route{
		LocalAddress:      localAddr,
		RemoteAddress:     snaddr,
		RemoteLinkAddress: broadcastMAC,
	}
	hdr := buffer.NewPrependable(int(linkEP.MaxHeaderLength()) + header.IPv6MinimumSize + header.ICMPv6NeighborAdvertSize)
	pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6NeighborAdvertSize))
	pkt.SetType(header.ICMPv6NeighborSolicit)
	copy(pkt[icmpV6OptOffset-len(addr):], addr)
	pkt[icmpV6OptOffset] = ndpOptSrcLinkAddr
	pkt[icmpV6LengthOffset] = 1
	copy(pkt[icmpV6LengthOffset+1:], linkEP.LinkAddress())
	pkt.SetChecksum(header.ICMPv6Checksum(pkt, r.LocalAddress, r.RemoteAddress, buffer.VectorisedView{}))

	length := uint16(hdr.UsedLength())
	ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize))
	ip.Encode(&header.IPv6Fields{
		PayloadLength: length,
		NextHeader:    uint8(header.ICMPv6ProtocolNumber),
		HopLimit:      header.NDPHopLimit,
		SrcAddr:       r.LocalAddress,
		DstAddr:       r.RemoteAddress,
	})

	// TODO(stijlist): count this in ICMP stats.
	return linkEP.WritePacket(r, nil /* gso */, hdr, buffer.VectorisedView{}, ProtocolNumber)
}

// ResolveStaticAddress implements stack.LinkAddressResolver.
func (*protocol) ResolveStaticAddress(addr tcpip.Address) (tcpip.LinkAddress, bool) {
	if header.IsV6MulticastAddress(addr) {
		// RFC 2464 Transmission of IPv6 Packets over Ethernet Networks
		//
		// 7. Address Mapping -- Multicast
		//
		// An IPv6 packet with a multicast destination address DST,
		// consisting of the sixteen octets DST[1] through DST[16], is
		// transmitted to the Ethernet multicast address whose first
		// two octets are the value 3333 hexadecimal and whose last
		// four octets are the last four octets of DST.
		return tcpip.LinkAddress([]byte{
			0x33,
			0x33,
			addr[header.IPv6AddressSize-4],
			addr[header.IPv6AddressSize-3],
			addr[header.IPv6AddressSize-2],
			addr[header.IPv6AddressSize-1],
		}), true
	}
	return "", false
}
