Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions WHATSNEW
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,10 @@ Notable bug fixes are the following:

The HT mode factory now includes band and preamble format in its cache key. A 5 GHz request after an equivalent 2.4 GHz request therefore receives the requested band and timing. Previously, that request could receive the earlier mode. Identical complete requests still reuse one object.

2. IPv6 routers keep link-local sources on their link

An IPv6 router forwarded a unicast datagram whose source address is link-local onto another link; it checked only the destination address. It now drops such a datagram and, unless the datagram is a Redirect, answers with ICMPv6 Destination Unreachable, code 2, "beyond scope of source address" (RFC 4291 Section 2.5.6, RFC 4007 Section 9). Sending the datagram back out of the interface it arrived on is still allowed. The Icmpv6DestUnav enum gains the value BEYOND_SCOPE_OF_SOURCE = 2. This changes the results of simulations in which a node sends from a link-local address to an off-link destination, for example before its global address is configured, or in which a router sends a Redirect to a node that is not its neighbour.


INET-4.7 (July 2026) — feature release
--------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/inet/networklayer/common/Icmpv6Type.msg
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ enum Icmpv6DestUnav

NO_ROUTE_TO_DEST = 0;
COMM_WITH_DEST_PROHIBITED = 1;
//2 - NOT ASSIGNED
BEYOND_SCOPE_OF_SOURCE = 2;
ADDRESS_UNREACHABLE = 3;
PORT_UNREACHABLE = 4;
}
Expand Down
22 changes: 22 additions & 0 deletions src/inet/networklayer/ipv6/Ipv6.cc
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,28 @@ void Ipv6::routePacket(Packet *packet, const NetworkInterface *destIE, const Net
return;
// don't raise error if sent to ND or ICMP!

// RFC 4291 Section 2.5.6, RFC 4007 Section 9: a datagram with a link-local source
// must not leave the link it arrived on. Without a zone model, the link is the
// arrival interface; a datagram sent back through it stays in its source's zone.
if (!fromHL && fromIE && interfaceId != fromIE->getInterfaceId() && ipv6Header->getSrcAddress().isLinkLocal()) {
EV_INFO << "source address is link-local and the datagram would leave its link, dropping\n";
numDropped++;
PacketDropDetails details;
details.setReason(OTHER_PACKET_DROP);
emit(packetDroppedSignal, packet, &details);
// RFC 4443 Section 2.4 (e.2): no ICMPv6 error message about a Redirect
bool isRedirect = false;
if (ipv6Header->getProtocolId() == IP_PROT_IPv6_ICMP) {
const auto& icmpHeader = packet->peekDataAt<Icmpv6Header>(ipv6Header->getChunkLength());
isRedirect = icmpHeader->getType() == ICMPv6_REDIRECT;
}
if (isRedirect)
delete packet;
else
sendIcmpError(packet, ICMPv6_DESTINATION_UNREACHABLE, BEYOND_SCOPE_OF_SOURCE);
return;
}

// RFC 4861 Section 8.2: a router sends a Redirect if it is forwarding a
// packet back out on the same interface it arrived on, to a different next-hop.
// Disabled (sendRedirects=false) on wireless multi-hop/ad-hoc networks, where the
Expand Down
6 changes: 3 additions & 3 deletions tests/fingerprint/examples.csv
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,9 @@
/examples/manetrouting/multiradio/, -f omnetpp.ini -c MultiRadio -r 0, 20s, 55c4-44c4/tplx;92b9-416a/~tNl, PASS, wireless adhoc Ipv4
/examples/manetrouting/multiradio/, -f omnetpp.ini -c SingleRadio -r 0, 20s, 5ed8-cf6b/tplx;b9f1-61b0/~tNl;3aa0-49ed/tyf, PASS, wireless adhoc Ipv4

/examples/ipv6/mipv6/, -f omnetpp.ini -c Handover -r 0, 70s, 68ea-9693/tplx;a44c-17bf/~tNl;96ff-ed7c/~tND;44ef-1a45/tyf, PASS, wireless EthernetMac
/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, bacf-986a/tplx;e6db-28c0/~tNl;805b-8a25/~tND;ed3e-17fa/tyf, PASS, wireless EthernetMac
/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, b275-b584/tplx;28ce-974e/~tNl;dcec-ae59/~tND;afae-2b3c/tyf, PASS, wireless EthernetMac
/examples/ipv6/mipv6/, -f omnetpp.ini -c Handover -r 0, 70s, 22cd-7897/tplx;b7dc-9169/~tNl;c9ba-d314/~tND;44ef-1a45/tyf, PASS, wireless EthernetMac
/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, 9473-84ec/tplx;0e27-f2af/~tNl;a224-1f60/~tND;ed3e-17fa/tyf, PASS, wireless EthernetMac
/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, ea06-4284/tplx;2913-f410/~tNl;22bb-d80d/~tND;afae-2b3c/tyf, PASS, wireless EthernetMac
/examples/ipv6/pmipv6/, -f omnetpp.ini -c General -r 0, 60s, e801-4d1a/tplx;1064-9bd4/~tNl;bd46-d85c/~tND;0277-d784/tyf, PASS, wireless EthernetMac

/examples/mobility/, -f omnetpp.ini -c AnsimMobility -r 0, 10000s, 72f8-5c0b/tplx;0000-0000/~tNl;0000-0000/~tND;7dd1-18eb/tyf, PASS,
Expand Down
69 changes: 69 additions & 0 deletions tests/module/IPv6_forwarding_link_local_source.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
%description:
Tests that a router does not forward a datagram with a link-local source address
onto another link (RFC 4291 Section 2.5.6, RFC 4007 Section 9), and that it
answers with ICMPv6 Destination Unreachable, code 2, "beyond scope of source
address" (RFC 4443 Section 3.1).

hostA pings hostB's global address from its own link-local address. The router
between them must drop the three Echo Requests instead of forwarding them to
hostB's link, and hostA must receive three Destination Unreachable messages with
code 2.

%#--------------------------------------------------------------------------------------------------------------
%file: test.ned
import inet.networklayer.configurator.ipv6.Ipv6FlatNetworkConfigurator;
import inet.node.ipv6.Router6;
import inet.node.ipv6.StandardHost6;
import ned.DatarateChannel;

network LinkLocalSourceNetwork
{
types:
channel ethline extends DatarateChannel
{
delay = 0.1us;
datarate = 100Mbps;
}
submodules:
configurator: Ipv6FlatNetworkConfigurator;
hostA: StandardHost6;
router: Router6;
hostB: StandardHost6;
connections:
hostA.ethg++ <--> ethline <--> router.ethg++;
router.ethg++ <--> ethline <--> hostB.ethg++;
}
%#--------------------------------------------------------------------------------------------------------------
%inifile: omnetpp.ini
[General]
record-vector-results = false
ned-path = ../../../../src
network = LinkLocalSourceNetwork
sim-time-limit = 6s
cmdenv-express-mode = false
cmdenv-log-prefix = "%C: "

**.hostA.eth[0].address = "0A:AA:00:00:00:0A"
**.hostA.numApps = 1
**.hostA.app[0].typename = "PingApp"
**.hostA.app[0].srcAddr = "fe80::8aa:ff:fe00:a"
**.hostA.app[0].destAddr = "hostB(ipv6)"
**.hostA.app[0].startTime = 4s
**.hostA.app[0].sendInterval = 0.5s
**.hostA.app[0].count = 3
%#--------------------------------------------------------------------------------------------------------------
%subst: /omnetpp:://
%#--------------------------------------------------------------------------------------------------------------
%not-contains-regex: stdout
LinkLocalSourceNetwork\.router\.ipv6\.ipv6: next hop for aaaa[^\n]*, interface eth1
%#--------------------------------------------------------------------------------------------------------------
%contains-regex: stdout
(LinkLocalSourceNetwork\.router\.ipv6\.ipv6: source address is link-local and the datagram would leave its link, dropping[\s\S]*){3}
%#--------------------------------------------------------------------------------------------------------------
%contains-regex: stdout
(LinkLocalSourceNetwork\.hostA\.ipv6\.lp: Dispatching packet[^\n]*Icmpv6DestUnreachableMsg[^\n]*code[^,\n]*= 2[\s\S]*){3}
%#--------------------------------------------------------------------------------------------------------------
%postrun-command: grep "undisposed object:" test.out > test_undisposed.out || true
%not-contains: test_undisposed.out
undisposed object: (
%#--------------------------------------------------------------------------------------------------------------
Loading