Skip to content

Conversation

@jagerman
Copy link
Member

No description provided.

jagerman and others added 23 commits October 23, 2025 15:11
Various fixes and "FIXME/TODO" completions to make IPv6 work internally.

- Fixed broken netlink address assignment
- Restores various explanatory comments from lokinet IP checksumming
  code that got removed for no valid reason.
- IPv6 checksum was just broken.
- IPv6 checksum was not being applied to ICMPv6, but needs to be
  because, unlike ICMPv4, the v6 checksum depends on the src/dest.
- Renamed/reorganized some IP checksum calculation that got less than
  optimally refactored in the lokinet->Session Router development.
- Drop DCCP handling, because it's a dead protocol that even the Linux
  kernel recently dropped support for.
It's very easy to accidentally put something like 172.16.0.0/16 of
fd42::/64 into the ifaddr setting, which isn't technically valid, so if
we are given the subnet 0 address, increment it by one and warn.

Also adds a check for IPv4 that we are not specifying the broadcast
address.  (IPv6 does not have a broadcast address).
- Allow it take both addresses (IPv4 & IPv6) for a pubkey on one line
- Make it fail on duplicates
- Improve its description
Everything in "net/utils.hpp" was just internal implementation details
of ip_packet.cpp, so put it back into ip_packet.cpp where it belongs.
Embedded mode is supposed to default to port 0 (if not specified), but
had inverted logic.  This fixes it.
this code shouldn't actually even be reachable at this time, but will be
soon and may as well work correctly.
this code shouldn't actually even be reachable at this time, but will be
soon and may as well work correctly.
- When a session expired, the IP was unmapped.  This meant that if you
  had looked up blocks.loki and started talking to it, but sent no
  traffic to it for a while, then tries to talk again the IP might have
  unmapped, and you would require another DNS lookup to keep talking.

  This commit changes the way we have mappings so that they expire
  before getting unmapped: while expired, traffic to that IP will
  revivify the Session to carry traffic and so the above cases don't
  happen.

  To keep the mapped list from growing indefinitely, this also adds a
  `expired-address-cache` setting that determines how many such expired
  mappings we retain: if we expire more than the limit then the oldest
  addresses are forgotten (in which case a DNS lookup or udp mapping
  call is required again).

- When an embedded session client expired, the UDP trampoline listener
  would get stopped, and so proxied UDP data would no longer work.  This
  reworks the UDP trampoline to be in SessionEndpoint instead of Session
  so that it can survive an expired Session and auto-vivify the Session
  if new trampoline traffic arrives while the port is still mapped.

  A new `close_udp()` method is added to allow an application to
  explicit close such a socket.

- Convert the UDP trampoline (i.e. "mapped udp") to use IPv6 instead of
  IPv4.

- Misc changes/fixes:
  - removed a pointless and unused third map from address_map.
    Amazingly, it turns out that you can implement a bidirection map
    using only two maps instead of three!
  - Updates "jank" test script for new APIs, but also gives it signal
    handling to allow removing/re-adding a UDP map.
  - Made the config of individual mappings more robust against invalid
    addresses or overlaps
  - Make the embedded API return the tunnel_info immediately so that a
    client can start sending even before the Session is established.
    (The callback is still present so that it can wait on the Session if
    needed).
  - Drop establish_udp_blocking().  It wasn't being used and is easy
    enough to implement yourself if you really want it.
  - Comment out the persistent address map handling for now as it isn't
    actually wired up.
It's very annoying to have this just fail when it could easily just
mkdir the directory you asked it to use.  (We don't, for instance,
require the user to mkdir nodedb inside it).
Relays use sr-tun@XXXXX by default now.
We were not noticing the not found status, and then warning on every not
found result because it failed to contain an "x" key.
This removes the default mapping of IPv4 addresses so that most internal
connections now speak only IPv6.  The only real use case we have for
IPv4 internally is for carrying IPv4 exit traffic, which we will revisit
and enable only when enabling exit mode.

This changes the IPv6 allocation to try assigning an IP based on the
pubkey of the remote first, so that, for instance, testnet decaf20
resolves to `fd2e:6c6f:6b69:0:deca:f200:25ca:6389` rather than
`fd2e:6c6f:6b69::2` (or whatever sequential value).  Sequential values
are still used as a fallback in case of pubkey prefix collision.

This also uncovered some bugs in how we respond to DNS queries:
- if requesting an A or AAAA record, we should only respond with that
  record type and not both the A/AAAA
- if requesting an A or AAAA and only an AAAA or A exists, we are
  supposed to return a NODATA reponse to indicate that the domain
  exists, but doesn't have the requested record type.  It doesn't seem
  as though we have ever done that properly, but now we do.
- The SERVFAIL response was commented out so if we didn't handle a
  request, DNS requests were just timing out.  This restores it.
Also fix jank test to not try to set the promise multiple times (and not
re-fire udp mapping if it loses and regains connectivity).
@jagerman jagerman changed the title [WIP] IPv6 support for internal connections IPv6 support for Session connections Oct 30, 2025
@jagerman jagerman merged commit 9f76642 into session-foundation:dev Oct 30, 2025
1 check passed
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.

2 participants