Make sure we have a selected route before accepting a TUN packet

Related to #614

Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
Lee Smet committed 2025-05-07 18:44:02 +02:00
1 parent 6f15ee1797
commit b954cda4b2
3 files changed
+49 -1

No files matched your search

+2
View File
@@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
for instance when using `traceroute`.
- Check the local seqno request cache before sending a seqno request to a peer,
to avoid spamming in certain occasions.
- Don't accept packet for a destination if we only have fallback routes for said
destination.
## [0.6.0] - 2025-04-25
+1 -1
View File
@@ -274,7 +274,7 @@ where
}
// Get shared secret from node and dest address
let shared_secret = match self.router.get_shared_secret_from_dest(dst_ip.into()) {
let shared_secret = match self.router.get_shared_secret_if_selected(dst_ip.into()) {
Some(ss) => ss,
// If we don't have a route to the destination subnet, reply with ICMP no route to
// host. Do this here as well to avoid encrypting the ICMP to ourselves.
+46
View File
@@ -260,6 +260,52 @@ where
}
}
/// Get a [`SharedSecret`] for a remote, if a selected route exists to the remote.
// TODO: Naming
pub fn get_shared_secret_if_selected(&self, dest: IpAddr) -> Option<SharedSecret> {
// TODO: proper fix
match self.routing_table.best_routes(dest) {
Routes::Exist(routes) => {
if routes.selected().is_some() {
Some(routes.shared_secret().clone())
} else {
// Optimistically try to fetch a new route for the subnet for next time.
// TODO: this can likely be handled better, but that relies on continuously
// quering routes in use, and handling unfeasible routes
if let Some(route_entry) = routes.iter().next() {
// We have a fallback route, use the source key from that to do a seqno
// request. Since the next hop might be dead, just do a broadcast. This
// might be blocked by the seqno request cache.
self.send_seqno_request(route_entry.source(), None, None);
} else {
// We don't have any routes, so send a route request. this might fail due
// to the source table.
self.send_route_request(
Subnet::new(dest, 64)
.expect("64 is a valid subnet size for an IPv6 address; qed"),
);
}
None
}
}
Routes::Queried => {
tokio::task::block_in_place(|| std::thread::sleep(QUERY_CHECK_DURATION));
self.get_shared_secret_if_selected(dest)
}
Routes::NoRoute => None,
Routes::None => {
// NOTE: we request the full /64 subnet
self.send_route_request(
Subnet::new(dest, 64)
.expect("64 is a valid subnet size for an IPv6 address; qed"),
);
tokio::task::block_in_place(|| std::thread::sleep(QUERY_CHECK_DURATION));
self.get_shared_secret_if_selected(dest)
}
}
}
/// Gets the cached [`SharedSecret`] based on the associated [`PublicKey`] of the remote.
#[inline]
pub fn get_shared_secret_by_pubkey(&self, dest: &PublicKey) -> Option<SharedSecret> {