Skip to content

ipv6: fix: keep a datagram with a link-local source on its link - #1358

Open
adamgeorge309 wants to merge 1 commit into
masterfrom
topic/gy/ipv6-link-local-source-scope
Open

adamgeorge309 wants to merge 1 commit into
masterfrom
topic/gy/ipv6-link-local-source-scope

Conversation

@adamgeorge309

Copy link
Copy Markdown
Contributor

An Internet Protocol version 6 (IPv6) router forwarded a unicast datagram whose source address is link-local onto another link, because Ipv6::routePacket() checked only the destination address. It now drops such a datagram and answers with an Internet Control Message Protocol for IPv6 (ICMPv6) Destination Unreachable message, code 2, "beyond scope of source address": Request for Comments (RFC) 4291 Section 2.5.6 forbids the forwarding, and RFC 4007 Section 9 requires the error.

Risk: simulations in which a node sends from its link-local address to an off-link destination, or in which a router's Redirect with a link-local source crosses another router, change. Three fingerprint rows of examples.csv (Mobile IPv6 (MIPv6) Handover, RouteOptimizationTwoCNs, Roaming) are re-recorded, and their statistical baselines in the statistics repository need re-recording after merge. Merge after #1256: without it, tests/module/IPv6_tunnel.test fails (see Verification).

Closes #1357

One commit: ipv6: fix: keep a datagram with a link-local source on its link.

The problem

src/inet/networklayer/ipv6/Ipv6.cc:479-484 on master refuses to forward a datagram with a link-local or loopback destination. Nothing on the forwarding path checks the source address, so a router forwards a datagram with an fe80::/10 source to any interface the routing table picks. Code 2 of Destination Unreachable was not defined: Icmpv6DestUnav had //2 - NOT ASSIGNED in its place.

The change

  • Ipv6::routePacket(), after the output interface is chosen and before the Redirect and FORWARD hook steps: a forwarded datagram (!fromHL, with an arrival interface) whose source is link-local and whose output interface differs from its arrival interface is dropped. INET has no zone model, so the arrival interface stands for the link. A datagram sent back out of its arrival interface stays on its link, so it does not leave the zone of its source address; that case, which is the Redirect trigger, is unchanged.
  • The drop increments numDropped, emits packetDropped with OTHER_PACKET_DROP, and calls sendIcmpError(..., ICMPv6_DESTINATION_UNREACHABLE, BEYOND_SCOPE_OF_SOURCE). No error is sent for a Redirect (RFC 4443 Section 2.4 (e.2)). Icmpv6::validateDatagramPromptingError() already suppresses errors about ICMPv6 errors, about multicast destinations, and about datagrams that arrived in a link-layer broadcast or multicast frame.
  • Icmpv6Type.msg: BEYOND_SCOPE_OF_SOURCE = 2 in Icmpv6DestUnav. The Transmission Control Protocol (TCP) treats it as a soft error: isHardIcmpv6Error() lists only codes 1 and 4.

No C++ interface, Network Description (NED) parameter, message field or feature descriptor changes; the enum gains one value.

Not addressed here: the error is routed like every other locally originated datagram to a link-local destination, by longest-prefix match over the fe80::/10 routes that every non-loopback interface adds. On a router where the arrival interface is not the one that match picks, the error leaves through the wrong interface and does not reach the sender. In the reproduction with the two links swapped, the 3 errors left through eth0 while hostA was on eth1. Pinning the error to the arrival interface would make it a datagram with an output interface but no next-hop determination, which is the separate defect of #1151 (pull request #1152).

Also not addressed: a datagram decapsulated at a tunnel exit keeps the physical interface the tunnel packet arrived on as its arrival interface. An inner datagram with a link-local source that leaves through that same interface is therefore still forwarded; one that leaves through another interface, as in IPv6_tunnel.test, is dropped. Multicast forwarding (routeMulticastPacket()) is unchanged. A datagram that goes out of another interface attached to the same link does not leave the zone either; without a zone model, it is now dropped.

Verification

Release build (make MODE=release in the root and tests/module/lib), each suite run on master bba1db4c81 and with this change.

New module test tests/module/IPv6_forwarding_link_local_source.test: hostA --- router --- hostB, hostA pings hostB's global address from fe80::8aa:ff:fe00:a. It checks that the router never logs a next hop on eth1 for hostB, that it logs the drop 3 times, and that hostA dispatches 3 Icmpv6DestUnreachableMsg with code 2. It fails on master (run before the master baseline), where the router forwards all 3 Echo Requests to hostB and hostB's replies to fe80::8aa:ff:fe00:a are dropped by the router as link-local destinations, and passes with this change.

Command Master This change
tests/fingerprint: ./fingerprinttest -s -F tyf 1774 run, 5 failures, 62 errors, 1 expected error 8 failures, the same 62 errors: the 3 rows below, which this commit re-records, and the same 5
tests/module: inet_run_module_tests -m release --no-build -l ERROR 657 run, 368 pass, 289 fail 658 run, 368 pass, 290 fail: the new test passes; IPv6_tunnel fails (below); the other failures are the same tests by name
tests/module: ... -f 'IPv6_tunnel|IPv6_forwarding_link_local_source' with #1256's commit ad02cc70ae applied on top both pass

Of the 289 module failures on master, 274 are tcp_* tests and 15 are ConvolutionalCoder12, ConvolutionalCoder34, DimensionalMediumAnalogModel_PrintAttenuation_1, EtherHost_lifecycle, ExternalProcess_3, Ieee80211BitDomain, Ieee80211BlockAckVariant_1, Ieee80211SymbolDomain, Ieee8021d-Rstp, Ieee8021d-Stp, IPv6_packet_too_big, LogNormalShadowing_Correlated_4, MIPv6_tcp_handover, PacketGate_1, UDPSocket_1. The 5 fingerprint failures on master are rows of mipv6-refactoring.csv whose recorded ~tNlb fingerprints are stale; the 62 errors are configurations whose optional features are not built.

IPv6_tunnel.test: host A sends into a tunnel interface whose exit is router B. On master the inner datagrams carry the link-local source fe80:: (#1255), and B forwarded them to H. With this change B drops them, all 8, and the test's "received 8 packets" check fails. #1256 gives those datagrams a global source.

Fingerprint rows: in examples.csv, examples/ipv6/mipv6 Handover and RouteOptimizationTwoCNs and examples/ipv6/mipv6roaming Roaming change their tplx, ~tNl and ~tND fingerprints, which this commit records. Their tyf fingerprints (./fingerprinttest -s -f tyf -m mipv6 examples.csv, run on master and with this change) differ from the recorded values on master too, and so does the pmipv6 row's tyf. These, and the 3 changed ~tNlb rows of mipv6-refactoring.csv, are left as they are. What changes in those runs, with this change:

The correspondent node's ping results (pingRxSeq:count, numLost:last) are the same in RouteOptimizationTwoCNs. In Handover, 112 replies arrive instead of 108 (sequence numbers 43, 125, 126 and 127 are added). In Roaming, 111 arrive instead of 112 (84 and 85 at 43.0 s and 43.5 s are lost, 122 at 62.0 s is added). In Roaming, no new drop happens near those times. In Handover, the home agent drops a returned Redirect at every reply in 22.5–39 s and 63.5–69.5 s, including the four added ones. Why only these replies change is not traced.

Gates: check-pull-request.sh --base origin/master (commits, classification, includes, NED parameters, description), check-source-seals.sh --base origin/master and check-architecture.sh src/inet/networklayer pass.

Relationship to other pull requests

Ipv6::routePacket() refused to forward a datagram whose destination address is link-local, but did not look at the source address, so a router forwarded a unicast datagram with a link-local source onto another link. Request for Comments (RFC) 4291 Section 2.5.6 says that routers must not forward packets with link-local source or destination addresses to other links, and RFC 4007 Section 9 discards a packet that would leave the zone of its source address and, for a unicast destination, answers with an Internet Control Message Protocol for Internet Protocol version 6 (ICMPv6) Destination Unreachable, code 2, "beyond scope of source address" (RFC 4443 Section 3.1).

After choosing the output interface, routePacket() now drops a forwarded datagram whose source is link-local if the output interface differs from the arrival interface (INET has no zone model, so the interface stands for the link; a datagram sent back through it stays in the zone of its source). The drop emits packetDropped with OTHER_PACKET_DROP and sends Destination Unreachable, code 2, unless the datagram is a Redirect (RFC 4443 Section 2.4 (e.2)). Icmpv6DestUnav gains BEYOND_SCOPE_OF_SOURCE = 2, where a comment stood.

tests/module/IPv6_forwarding_link_local_source.test pings an off-link host from a link-local address through a router and checks that the router forwards none of the 3 Echo Requests and that the sender receives 3 Destination Unreachable messages with code 2; before this commit, the router forwarded all 3.

This commit records the changed tplx, ~tNl and ~tND fingerprints of three examples.csv rows: examples/ipv6/mipv6 Handover and RouteOptimizationTwoCNs, examples/ipv6/mipv6roaming Roaming. In Handover and Roaming, a correspondent node pings from its link-local address before it has a global address; in all three, the home agent used to tunnel its own Redirects, returned by a router, to the mobile node. Their tyf fingerprints and the mipv6-refactoring.csv rows, which fail on master, are kept. The statistical baselines of the three configurations change.

Change: src.networklayer.ipv6.Ipv6 | behavior.change.fix | test fingerprint statistical whatsnew

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ipv6: a router forwards a datagram whose source address is link-local onto another link

1 participant