Merge release-20201030.0-91-g6c0f53002 (automated)
This commit is contained in:
commit
4e9636928b
|
@ -54,7 +54,7 @@ type IPv6Fields struct {
|
||||||
// NextHeader is the "next header" field of an IPv6 packet.
|
// NextHeader is the "next header" field of an IPv6 packet.
|
||||||
NextHeader uint8
|
NextHeader uint8
|
||||||
|
|
||||||
// HopLimit is the "hop limit" field of an IPv6 packet.
|
// HopLimit is the "Hop Limit" field of an IPv6 packet.
|
||||||
HopLimit uint8
|
HopLimit uint8
|
||||||
|
|
||||||
// SrcAddr is the "source ip address" of an IPv6 packet.
|
// SrcAddr is the "source ip address" of an IPv6 packet.
|
||||||
|
@ -171,7 +171,7 @@ func (b IPv6) PayloadLength() uint16 {
|
||||||
return binary.BigEndian.Uint16(b[IPv6PayloadLenOffset:])
|
return binary.BigEndian.Uint16(b[IPv6PayloadLenOffset:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// HopLimit returns the value of the "hop limit" field of the ipv6 header.
|
// HopLimit returns the value of the "Hop Limit" field of the ipv6 header.
|
||||||
func (b IPv6) HopLimit() uint8 {
|
func (b IPv6) HopLimit() uint8 {
|
||||||
return b[hopLimit]
|
return b[hopLimit]
|
||||||
}
|
}
|
||||||
|
@ -236,6 +236,11 @@ func (b IPv6) SetDestinationAddress(addr tcpip.Address) {
|
||||||
copy(b[v6DstAddr:][:IPv6AddressSize], addr)
|
copy(b[v6DstAddr:][:IPv6AddressSize], addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetHopLimit sets the value of the "Hop Limit" field.
|
||||||
|
func (b IPv6) SetHopLimit(v uint8) {
|
||||||
|
b[hopLimit] = v
|
||||||
|
}
|
||||||
|
|
||||||
// SetNextHeader sets the value of the "next header" field of the ipv6 header.
|
// SetNextHeader sets the value of the "next header" field of the ipv6 header.
|
||||||
func (b IPv6) SetNextHeader(v uint8) {
|
func (b IPv6) SetNextHeader(v uint8) {
|
||||||
b[IPv6NextHeaderOffset] = v
|
b[IPv6NextHeaderOffset] = v
|
||||||
|
|
|
@ -290,6 +290,13 @@ type icmpReasonProtoUnreachable struct{}
|
||||||
|
|
||||||
func (*icmpReasonProtoUnreachable) isICMPReason() {}
|
func (*icmpReasonProtoUnreachable) isICMPReason() {}
|
||||||
|
|
||||||
|
// icmpReasonTTLExceeded is an error where a packet's time to live exceeded in
|
||||||
|
// transit to its final destination, as per RFC 792 page 6, Time Exceeded
|
||||||
|
// Message.
|
||||||
|
type icmpReasonTTLExceeded struct{}
|
||||||
|
|
||||||
|
func (*icmpReasonTTLExceeded) isICMPReason() {}
|
||||||
|
|
||||||
// icmpReasonReassemblyTimeout is an error where insufficient fragments are
|
// icmpReasonReassemblyTimeout is an error where insufficient fragments are
|
||||||
// received to complete reassembly of a packet within a configured time after
|
// received to complete reassembly of a packet within a configured time after
|
||||||
// the reception of the first-arriving fragment of that packet.
|
// the reception of the first-arriving fragment of that packet.
|
||||||
|
@ -342,11 +349,31 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) *tcpi
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we hit a TTL Exceeded error, then we know we are operating as a router.
|
||||||
|
// As per RFC 792 page 6, Time Exceeded Message,
|
||||||
|
//
|
||||||
|
// If the gateway processing a datagram finds the time to live field
|
||||||
|
// is zero it must discard the datagram. The gateway may also notify
|
||||||
|
// the source host via the time exceeded message.
|
||||||
|
//
|
||||||
|
// ...
|
||||||
|
//
|
||||||
|
// Code 0 may be received from a gateway. ...
|
||||||
|
//
|
||||||
|
// Note, Code 0 is the TTL exceeded error.
|
||||||
|
//
|
||||||
|
// If we are operating as a router/gateway, don't use the packet's destination
|
||||||
|
// address as the response's source address as we should not not own the
|
||||||
|
// destination address of a packet we are forwarding.
|
||||||
|
localAddr := origIPHdrDst
|
||||||
|
if _, ok := reason.(*icmpReasonTTLExceeded); ok {
|
||||||
|
localAddr = ""
|
||||||
|
}
|
||||||
// Even if we were able to receive a packet from some remote, we may not have
|
// Even if we were able to receive a packet from some remote, we may not have
|
||||||
// a route to it - the remote may be blocked via routing rules. We must always
|
// a route to it - the remote may be blocked via routing rules. We must always
|
||||||
// consult our routing table and find a route to the remote before sending any
|
// consult our routing table and find a route to the remote before sending any
|
||||||
// packet.
|
// packet.
|
||||||
route, err := p.stack.FindRoute(pkt.NICID, origIPHdrDst, origIPHdrSrc, ProtocolNumber, false /* multicastLoop */)
|
route, err := p.stack.FindRoute(pkt.NICID, localAddr, origIPHdrSrc, ProtocolNumber, false /* multicastLoop */)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -454,6 +481,10 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) *tcpi
|
||||||
icmpHdr.SetType(header.ICMPv4DstUnreachable)
|
icmpHdr.SetType(header.ICMPv4DstUnreachable)
|
||||||
icmpHdr.SetCode(header.ICMPv4ProtoUnreachable)
|
icmpHdr.SetCode(header.ICMPv4ProtoUnreachable)
|
||||||
counter = sent.DstUnreachable
|
counter = sent.DstUnreachable
|
||||||
|
case *icmpReasonTTLExceeded:
|
||||||
|
icmpHdr.SetType(header.ICMPv4TimeExceeded)
|
||||||
|
icmpHdr.SetCode(header.ICMPv4TTLExceeded)
|
||||||
|
counter = sent.TimeExceeded
|
||||||
case *icmpReasonReassemblyTimeout:
|
case *icmpReasonReassemblyTimeout:
|
||||||
icmpHdr.SetType(header.ICMPv4TimeExceeded)
|
icmpHdr.SetType(header.ICMPv4TimeExceeded)
|
||||||
icmpHdr.SetCode(header.ICMPv4ReassemblyTimeout)
|
icmpHdr.SetCode(header.ICMPv4ReassemblyTimeout)
|
||||||
|
|
|
@ -485,6 +485,16 @@ func (e *endpoint) WriteHeaderIncludedPacket(r *stack.Route, pkt *stack.PacketBu
|
||||||
// forwardPacket attempts to forward a packet to its final destination.
|
// forwardPacket attempts to forward a packet to its final destination.
|
||||||
func (e *endpoint) forwardPacket(pkt *stack.PacketBuffer) *tcpip.Error {
|
func (e *endpoint) forwardPacket(pkt *stack.PacketBuffer) *tcpip.Error {
|
||||||
h := header.IPv4(pkt.NetworkHeader().View())
|
h := header.IPv4(pkt.NetworkHeader().View())
|
||||||
|
ttl := h.TTL()
|
||||||
|
if ttl == 0 {
|
||||||
|
// As per RFC 792 page 6, Time Exceeded Message,
|
||||||
|
//
|
||||||
|
// If the gateway processing a datagram finds the time to live field
|
||||||
|
// is zero it must discard the datagram. The gateway may also notify
|
||||||
|
// the source host via the time exceeded message.
|
||||||
|
return e.protocol.returnError(&icmpReasonTTLExceeded{}, pkt)
|
||||||
|
}
|
||||||
|
|
||||||
dstAddr := h.DestinationAddress()
|
dstAddr := h.DestinationAddress()
|
||||||
|
|
||||||
// Check if the destination is owned by the stack.
|
// Check if the destination is owned by the stack.
|
||||||
|
@ -503,13 +513,22 @@ func (e *endpoint) forwardPacket(pkt *stack.PacketBuffer) *tcpip.Error {
|
||||||
}
|
}
|
||||||
defer r.Release()
|
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.IPv4(stack.PayloadSince(pkt.NetworkHeader()))
|
||||||
|
|
||||||
|
// As per RFC 791 page 30, Time to Live,
|
||||||
|
//
|
||||||
|
// This field must be decreased at each point that the internet header
|
||||||
|
// is processed to reflect the time spent processing the datagram.
|
||||||
|
// Even if no local information is available on the time actually
|
||||||
|
// spent, the field must be decremented by 1.
|
||||||
|
newHdr.SetTTL(ttl - 1)
|
||||||
|
|
||||||
return r.WriteHeaderIncludedPacket(stack.NewPacketBuffer(stack.PacketBufferOptions{
|
return r.WriteHeaderIncludedPacket(stack.NewPacketBuffer(stack.PacketBufferOptions{
|
||||||
ReserveHeaderBytes: int(r.MaxHeaderLength()),
|
ReserveHeaderBytes: int(r.MaxHeaderLength()),
|
||||||
// We need to do a deep copy of the IP packet because
|
Data: buffer.View(newHdr).ToVectorisedView(),
|
||||||
// WriteHeaderIncludedPacket takes ownership of the packet buffer, but we do
|
|
||||||
// not own it.
|
|
||||||
Data: stack.PayloadSince(pkt.NetworkHeader()).ToVectorisedView(),
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -750,6 +750,12 @@ type icmpReasonPortUnreachable struct{}
|
||||||
|
|
||||||
func (*icmpReasonPortUnreachable) isICMPReason() {}
|
func (*icmpReasonPortUnreachable) isICMPReason() {}
|
||||||
|
|
||||||
|
// icmpReasonHopLimitExceeded is an error where a packet's hop limit exceeded in
|
||||||
|
// transit to its final destination, as per RFC 4443 section 3.3.
|
||||||
|
type icmpReasonHopLimitExceeded struct{}
|
||||||
|
|
||||||
|
func (*icmpReasonHopLimitExceeded) isICMPReason() {}
|
||||||
|
|
||||||
// icmpReasonReassemblyTimeout is an error where insufficient fragments are
|
// icmpReasonReassemblyTimeout is an error where insufficient fragments are
|
||||||
// received to complete reassembly of a packet within a configured time after
|
// received to complete reassembly of a packet within a configured time after
|
||||||
// the reception of the first-arriving fragment of that packet.
|
// the reception of the first-arriving fragment of that packet.
|
||||||
|
@ -794,11 +800,27 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) *tcpi
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we hit a Hop Limit Exceeded error, then we know we are operating as a
|
||||||
|
// router. 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.
|
||||||
|
//
|
||||||
|
// If we are operating as a router, do not use the packet's destination
|
||||||
|
// address as the response's source address as we should not own the
|
||||||
|
// destination address of a packet we are forwarding.
|
||||||
|
localAddr := origIPHdrDst
|
||||||
|
if _, ok := reason.(*icmpReasonHopLimitExceeded); ok {
|
||||||
|
localAddr = ""
|
||||||
|
}
|
||||||
// Even if we were able to receive a packet from some remote, we may not have
|
// Even if we were able to receive a packet from some remote, we may not have
|
||||||
// a route to it - the remote may be blocked via routing rules. We must always
|
// a route to it - the remote may be blocked via routing rules. We must always
|
||||||
// consult our routing table and find a route to the remote before sending any
|
// consult our routing table and find a route to the remote before sending any
|
||||||
// packet.
|
// packet.
|
||||||
route, err := p.stack.FindRoute(pkt.NICID, origIPHdrDst, origIPHdrSrc, ProtocolNumber, false /* multicastLoop */)
|
route, err := p.stack.FindRoute(pkt.NICID, localAddr, origIPHdrSrc, ProtocolNumber, false /* multicastLoop */)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -811,8 +833,6 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) *tcpi
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
network, transport := pkt.NetworkHeader().View(), pkt.TransportHeader().View()
|
|
||||||
|
|
||||||
if pkt.TransportProtocolNumber == header.ICMPv6ProtocolNumber {
|
if pkt.TransportProtocolNumber == header.ICMPv6ProtocolNumber {
|
||||||
// TODO(gvisor.dev/issues/3810): Sort this out when ICMP headers are stored.
|
// TODO(gvisor.dev/issues/3810): Sort this out when ICMP headers are stored.
|
||||||
// Unfortunately at this time ICMP Packets do not have a transport
|
// Unfortunately at this time ICMP Packets do not have a transport
|
||||||
|
@ -830,6 +850,8 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) *tcpi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
network, transport := pkt.NetworkHeader().View(), pkt.TransportHeader().View()
|
||||||
|
|
||||||
// As per RFC 4443 section 2.4
|
// As per RFC 4443 section 2.4
|
||||||
//
|
//
|
||||||
// (c) Every ICMPv6 error message (type < 128) MUST include
|
// (c) Every ICMPv6 error message (type < 128) MUST include
|
||||||
|
@ -873,6 +895,10 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) *tcpi
|
||||||
icmpHdr.SetType(header.ICMPv6DstUnreachable)
|
icmpHdr.SetType(header.ICMPv6DstUnreachable)
|
||||||
icmpHdr.SetCode(header.ICMPv6PortUnreachable)
|
icmpHdr.SetCode(header.ICMPv6PortUnreachable)
|
||||||
counter = sent.DstUnreachable
|
counter = sent.DstUnreachable
|
||||||
|
case *icmpReasonHopLimitExceeded:
|
||||||
|
icmpHdr.SetType(header.ICMPv6TimeExceeded)
|
||||||
|
icmpHdr.SetCode(header.ICMPv6HopLimitExceeded)
|
||||||
|
counter = sent.TimeExceeded
|
||||||
case *icmpReasonReassemblyTimeout:
|
case *icmpReasonReassemblyTimeout:
|
||||||
icmpHdr.SetType(header.ICMPv6TimeExceeded)
|
icmpHdr.SetType(header.ICMPv6TimeExceeded)
|
||||||
icmpHdr.SetCode(header.ICMPv6ReassemblyTimeout)
|
icmpHdr.SetCode(header.ICMPv6ReassemblyTimeout)
|
||||||
|
|
|
@ -645,6 +645,18 @@ func (e *endpoint) WriteHeaderIncludedPacket(r *stack.Route, pkt *stack.PacketBu
|
||||||
// forwardPacket attempts to forward a packet to its final destination.
|
// forwardPacket attempts to forward a packet to its final destination.
|
||||||
func (e *endpoint) forwardPacket(pkt *stack.PacketBuffer) *tcpip.Error {
|
func (e *endpoint) forwardPacket(pkt *stack.PacketBuffer) *tcpip.Error {
|
||||||
h := header.IPv6(pkt.NetworkHeader().View())
|
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()
|
dstAddr := h.DestinationAddress()
|
||||||
|
|
||||||
// Check if the destination is owned by the stack.
|
// 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()
|
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{
|
return r.WriteHeaderIncludedPacket(stack.NewPacketBuffer(stack.PacketBufferOptions{
|
||||||
ReserveHeaderBytes: int(r.MaxHeaderLength()),
|
ReserveHeaderBytes: int(r.MaxHeaderLength()),
|
||||||
// We need to do a deep copy of the IP packet because
|
Data: buffer.View(newHdr).ToVectorisedView(),
|
||||||
// WriteHeaderIncludedPacket takes ownership of the packet buffer, but we do
|
|
||||||
// not own it.
|
|
||||||
Data: stack.PayloadSince(pkt.NetworkHeader()).ToVectorisedView(),
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue