summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/network/ipv6/icmp.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tcpip/network/ipv6/icmp.go')
-rw-r--r--pkg/tcpip/network/ipv6/icmp.go78
1 files changed, 59 insertions, 19 deletions
diff --git a/pkg/tcpip/network/ipv6/icmp.go b/pkg/tcpip/network/ipv6/icmp.go
index 247a07dc2..4051fda07 100644
--- a/pkg/tcpip/network/ipv6/icmp.go
+++ b/pkg/tcpip/network/ipv6/icmp.go
@@ -955,7 +955,19 @@ func (*endpoint) ResolveStaticAddress(addr tcpip.Address) (tcpip.LinkAddress, bo
// icmpReason is a marker interface for IPv6 specific ICMP errors.
type icmpReason interface {
isICMPReason()
+ // isForwarding indicates whether or not the error arose while attempting to
+ // forward a packet.
isForwarding() bool
+ // respondToMulticast indicates whether this error falls under the exception
+ // outlined by RFC 4443 section 2.4 point e.3 exception 2:
+ //
+ // (e.3) A packet destined to an IPv6 multicast address. (There are two
+ // exceptions to this rule: (1) the Packet Too Big Message (Section 3.2) to
+ // allow Path MTU discovery to work for IPv6 multicast, and (2) the Parameter
+ // Problem Message, Code 2 (Section 3.4) reporting an unrecognized IPv6
+ // option (see Section 4.2 of [IPv6]) that has the Option Type highest-
+ // order two bits set to 10).
+ respondsToMulticast() bool
}
// icmpReasonParameterProblem is an error during processing of extension headers
@@ -963,18 +975,6 @@ type icmpReason interface {
type icmpReasonParameterProblem struct {
code header.ICMPv6Code
- // respondToMulticast indicates that we are sending a packet that falls under
- // the exception outlined by RFC 4443 section 2.4 point e.3 exception 2:
- //
- // (e.3) A packet destined to an IPv6 multicast address. (There are
- // two exceptions to this rule: (1) the Packet Too Big Message
- // (Section 3.2) to allow Path MTU discovery to work for IPv6
- // multicast, and (2) the Parameter Problem Message, Code 2
- // (Section 3.4) reporting an unrecognized IPv6 option (see
- // Section 4.2 of [IPv6]) that has the Option Type highest-
- // order two bits set to 10).
- respondToMulticast bool
-
// pointer is defined in the RFC 4443 setion 3.4 which reads:
//
// Pointer Identifies the octet offset within the invoking packet
@@ -985,9 +985,9 @@ type icmpReasonParameterProblem struct {
// in the maximum size of an ICMPv6 error message.
pointer uint32
- // forwarding indicates that the problem arose while we were trying to forward
- // a packet.
forwarding bool
+
+ respondToMulticast bool
}
func (*icmpReasonParameterProblem) isICMPReason() {}
@@ -995,6 +995,10 @@ func (p *icmpReasonParameterProblem) isForwarding() bool {
return p.forwarding
}
+func (p *icmpReasonParameterProblem) respondsToMulticast() bool {
+ return p.respondToMulticast
+}
+
// icmpReasonPortUnreachable is an error where the transport protocol has no
// listener and no alternative means to inform the sender.
type icmpReasonPortUnreachable struct{}
@@ -1005,6 +1009,10 @@ func (*icmpReasonPortUnreachable) isForwarding() bool {
return false
}
+func (*icmpReasonPortUnreachable) respondsToMulticast() bool {
+ return false
+}
+
// icmpReasonNetUnreachable is an error where no route can be found to the
// network of the final destination.
type icmpReasonNetUnreachable struct{}
@@ -1021,6 +1029,30 @@ func (*icmpReasonNetUnreachable) isForwarding() bool {
return true
}
+func (*icmpReasonNetUnreachable) respondsToMulticast() bool {
+ return false
+}
+
+// icmpReasonFragmentationNeeded is an error where a packet is to big to be sent
+// out through the outgoing MTU, as per RFC 4443 page 9, Packet Too Big Message.
+type icmpReasonPacketTooBig struct{}
+
+func (*icmpReasonPacketTooBig) isICMPReason() {}
+
+func (*icmpReasonPacketTooBig) isForwarding() bool {
+ // If we hit a Packet Too Big error, then we know we are operating as a router.
+ // As per RFC 4443 section 3.2:
+ //
+ // A Packet Too Big MUST be sent by a router in response to a packet that it
+ // cannot forward because the packet is larger than the MTU of the outgoing
+ // link.
+ return true
+}
+
+func (*icmpReasonPacketTooBig) respondsToMulticast() bool {
+ return true
+}
+
// 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{}
@@ -1039,6 +1071,10 @@ func (*icmpReasonHopLimitExceeded) isForwarding() bool {
return true
}
+func (*icmpReasonHopLimitExceeded) respondsToMulticast() bool {
+ return false
+}
+
// icmpReasonReassemblyTimeout is an error where insufficient fragments are
// received to complete reassembly of a packet within a configured time after
// the reception of the first-arriving fragment of that packet.
@@ -1050,6 +1086,10 @@ func (*icmpReasonReassemblyTimeout) isForwarding() bool {
return false
}
+func (*icmpReasonReassemblyTimeout) respondsToMulticast() bool {
+ return false
+}
+
// returnError takes an error descriptor and generates the appropriate ICMP
// error packet for IPv6 and sends it.
func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) tcpip.Error {
@@ -1078,11 +1118,7 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) tcpip
// Section 4.2 of [IPv6]) that has the Option Type highest-
// order two bits set to 10).
//
- var allowResponseToMulticast bool
- if reason, ok := reason.(*icmpReasonParameterProblem); ok {
- allowResponseToMulticast = reason.respondToMulticast
- }
-
+ allowResponseToMulticast := reason.respondsToMulticast()
isOrigDstMulticast := header.IsV6MulticastAddress(origIPHdrDst)
if (!allowResponseToMulticast && isOrigDstMulticast) || origIPHdrSrc == header.IPv6Any {
return nil
@@ -1190,6 +1226,10 @@ func (p *protocol) returnError(reason icmpReason, pkt *stack.PacketBuffer) tcpip
icmpHdr.SetType(header.ICMPv6DstUnreachable)
icmpHdr.SetCode(header.ICMPv6NetworkUnreachable)
counter = sent.dstUnreachable
+ case *icmpReasonPacketTooBig:
+ icmpHdr.SetType(header.ICMPv6PacketTooBig)
+ icmpHdr.SetCode(header.ICMPv6UnusedCode)
+ counter = sent.packetTooBig
case *icmpReasonHopLimitExceeded:
icmpHdr.SetType(header.ICMPv6TimeExceeded)
icmpHdr.SetCode(header.ICMPv6HopLimitExceeded)