From 6c0f53002a7f3a518befbe667d308c3d64cc9a59 Mon Sep 17 00:00:00 2001 From: Ghanan Gowripalan Date: Fri, 13 Nov 2020 13:10:51 -0800 Subject: Decrement TTL/Hop Limit when forwarding IP packets If the packet must no longer be forwarded because its TTL/Hop Limit reaches 0, send an ICMP Time Exceeded error to the source. Required as per relevant RFCs. See comments in code for RFC references. Fixes #1085 Tests: - ipv4_test.TestForwarding - ipv6.TestForwarding PiperOrigin-RevId: 342323610 --- pkg/tcpip/network/ipv6/ipv6.go | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'pkg/tcpip/network/ipv6/ipv6.go') diff --git a/pkg/tcpip/network/ipv6/ipv6.go b/pkg/tcpip/network/ipv6/ipv6.go index 38a0633bd..7697ff987 100644 --- a/pkg/tcpip/network/ipv6/ipv6.go +++ b/pkg/tcpip/network/ipv6/ipv6.go @@ -645,6 +645,18 @@ func (e *endpoint) WriteHeaderIncludedPacket(r *stack.Route, pkt *stack.PacketBu // forwardPacket attempts to forward a packet to its final destination. func (e *endpoint) forwardPacket(pkt *stack.PacketBuffer) *tcpip.Error { h := header.IPv6(pkt.NetworkHeader().View()) + hopLimit := h.HopLimit() + if hopLimit <= 1 { + // As per RFC 4443 section 3.3, + // + // If a router receives a packet with a Hop Limit of zero, or if a + // router decrements a packet's Hop Limit to zero, it MUST discard the + // packet and originate an ICMPv6 Time Exceeded message with Code 0 to + // the source of the packet. This indicates either a routing loop or + // too small an initial Hop Limit value. + return e.protocol.returnError(&icmpReasonHopLimitExceeded{}, pkt) + } + dstAddr := h.DestinationAddress() // Check if the destination is owned by the stack. @@ -663,13 +675,20 @@ func (e *endpoint) forwardPacket(pkt *stack.PacketBuffer) *tcpip.Error { } defer r.Release() - // TODO(b/143425874) Decrease the TTL field in forwarded packets. + // We need to do a deep copy of the IP packet because + // WriteHeaderIncludedPacket takes ownership of the packet buffer, but we do + // not own it. + newHdr := header.IPv6(stack.PayloadSince(pkt.NetworkHeader())) + + // As per RFC 8200 section 3, + // + // Hop Limit 8-bit unsigned integer. Decremented by 1 by + // each node that forwards the packet. + newHdr.SetHopLimit(hopLimit - 1) + return r.WriteHeaderIncludedPacket(stack.NewPacketBuffer(stack.PacketBufferOptions{ ReserveHeaderBytes: int(r.MaxHeaderLength()), - // We need to do a deep copy of the IP packet because - // WriteHeaderIncludedPacket takes ownership of the packet buffer, but we do - // not own it. - Data: stack.PayloadSince(pkt.NetworkHeader()).ToVectorisedView(), + Data: buffer.View(newHdr).ToVectorisedView(), })) } -- cgit v1.2.3