Skip to content

Sets the managed-mode LAN's IPv6 prefix the way it sets the IPv4 gateway, picked at random once - #18

Open
poqdavid wants to merge 9 commits into
ravindu644:mainfrom
poqdavid:managed-ula-prefix
Open

poqdavid wants to merge 9 commits into
ravindu644:mainfrom
poqdavid:managed-ula-prefix

Conversation

@poqdavid

@poqdavid poqdavid commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Problem

In managed mode VirtualAP writes the LAN's IPv4 side into the container itself (network.vaplan.ipaddr from IP_GW), but the IPv6 side was left to ip6assign 64, a /64 out of whatever ULA the container happened to generate at first boot. The hotspot's IPv6 prefix couldn't be seen or set from the app, changing it meant editing the container by hand, and a new or reinstalled container came with a new ULA, so every client on the hotspot was renumbered with it.

Fix

The backend gets -u <prefix>, saved in ap.conf as ULA: a /48 in fd00::/8. openwrt_provision() sets network.vaplan.ip6addr to its /64 numbered after the gateway's third octet, the same way the ip6hint from #6 and the routed NAT66 /64 number it, with ::1 as the gateway, the way .1 is for IPv4. So fd12:3456:789a::/48 with 192.168.42.1 gives fd12:3456:789a:42::1/64. It's written on every start, so a changed prefix replaces the old one, and ip6assign is removed so the container doesn't add a second /64 from its own ULA beside it. Empty, the default, keeps today's behaviour: a /64 from the container's ULA, pinned by ip6hint. A prefix outside fd00::/8, one that isn't a /48, or Droidspaces' own fd64:7370::/48, which the container's uplink already uses, is a warning and falls back to that default, not a failed start. ula_lan() has a test in tests/check.c.

In the app, the Advanced card in managed mode gets an IPv6 prefix box under the gateway MAC. It holds a random /48 (RFC 4193's 40 random bits after fd), picked once and kept in ap.conf, so no two hotspots share a prefix. It's editable, and it shows the /64 and gateway the hotspot will get. An invalid prefix blocks Start through APConfig.isValid(), so the Quick Settings tile follows it too. Anyone who wants to keep the prefix their container already hands out can type its ULA in, and the hotspot stays on the same /64.

How-It-Works.md describes the setting and its fallback.

Tested on my device in managed mode with the OpenWrt container

Image

-u <prefix> (ULA in ap.conf) takes a /48 in fd00::/8 and sets vaplan's
ip6addr to its /64 numbered after the gateway's third octet, ::1 for
the gateway, the way ipaddr sets the IPv4 side. It is written on every
start, so a changed prefix replaces the old one. Empty, the default,
keeps the /64 from the container's own ULA. Droidspaces' fd64:7370::/48
is refused, since the container's uplink uses it.

Signed-off-by: poqdavid <poq-david@live.com>
Managed mode's Advanced card gets an IPv6 prefix box: a random /48 in
fd00::/8 picked once and kept in ap.conf, editable, showing the /64 and
gateway the hotspot gets. An invalid prefix blocks Start through
isValid().

Signed-off-by: poqdavid <poq-david@live.com>
How-It-Works describes the ULA setting, its fallback to the container's
own ULA, and that both addresses are rewritten on every start.

Signed-off-by: poqdavid <poq-david@live.com>
@kokoromagic

Copy link
Copy Markdown

It is better to allow the address to be specified manually.

Example: I can use 203.0.113.1/24 for ipv4 hotspot gateway and I can use 2001:db8::/32 or 3fff::/20 for ipv6 hotspot address

@poqdavid

poqdavid commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

It is better to allow the address to be specified manually.

Example: I can use 203.0.113.1/24 for ipv4 hotspot gateway and I can use 2001:db8::/32 or 3fff::/20 for ipv6 hotspot address

Oh thats a good point i will make that change while keeping the once randomly generated ula and i will add another setting for specifying ipv6 address under the ipv4

-G <address> (IP6_GW in ap.conf) sets vaplan's ip6addr to that address
with its /64, ahead of -u. It takes a global or unique local unicast
address, in 2000::/3 or fc00::/7, bare or with /64, and a bare /64 gets
::1. On a ULA-only LAN clients rank IPv6 below IPv4 and barely use it;
a prefix outside fc00::/7, such as 2001:db8::/32 or 3fff::/20, makes
them prefer it. Anything else, or an address in Droidspaces'
fd64:7370::/48, is refused with a warning and -u applies. Managed mode
only.

Signed-off-by: poqdavid <poq-david@live.com>
Managed mode's Advanced card gets an IPv6 gateway box under Gateway IP,
saved as IP6_GW, with the address the IPv6 prefix gives as its hint.
The prefix box moves up under it, out of the MAC boxes, and is greyed
out but kept while a gateway is set, so clearing the gateway brings the
same /64 back. The address is parsed by hand: InetAddress sends what it
cannot parse to DNS, and the numeric-only parser needs API 29.

Signed-off-by: poqdavid <poq-david@live.com>
How-It-Works lists where the LAN's IPv6 comes from, IP6_GW first, why a
prefix outside fc00::/7 matters to clients, and that it needs masq6 in
the container to get out.

Signed-off-by: poqdavid <poq-david@live.com>
@poqdavid

poqdavid commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

I just did some changes once i finish testing them i will add a screenshot of the changes as well

@poqdavid

poqdavid commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor Author

What's new

  • New setting IP6_GW (-G <address>), managed mode only. It sets the LAN gateway's IPv6 address directly, the way Gateway IP sets the IPv4 one.

    • Takes any global or unique local unicast address (2000::/3 or fc00::/7), with or without /64. For example: 2001:db8::1, 3fff::1, fd9b:eb8c:afef:42::1.
    • The LAN is always that address's /64. Clients configure themselves by SLAAC, which needs a /64, and Android has no DHCPv6 address assignment. A bare /64 like 2001:db8::/64 gets ::1 as the gateway.
    • Refused with a warning in the log: other prefix lengths, link-local, multicast, loopback, IPv4-mapped, and Droidspaces' own fd64:7370::/48.
  • The random-once ULA stays as the default. The LAN's IPv6 comes from the first of these that's set:

    1. IP6_GW, used as typed
    2. ULA, the random /48, numbered after the IPv4 third octet (fdxx:xxxx:xxxx:42::1/64 for 192.168.42.1)
    3. Neither: a /64 from the container's own ULA, as before

    Setting a gateway doesn't delete the ULA, so clearing the gateway brings the same /64 back.

Why it matters

The container still has to route that IPv6 out (with fw3, an ip6tables MASQUERADE rule from a firewall include; with fw4, masq6 on the wan zone); otherwise clients try IPv6 first and then fall back to IPv4.

UI

In managed mode, the Advanced section is now ordered: Gateway IP → IPv6 gateway → IPv6 prefix → MAC mode → MAC address. The IPv6 gateway box shows the address the prefix would give as its hint. The prefix box is greyed out while a gateway is set.

@kokoromagic Thanks for the suggestion about setting the address by hand. I've pushed a few more commits on top of the ULA prefix work.

The script provisions fw3 on iptables-legacy, which has no masq6 option:
there the LAN's IPv6 goes out through an ip6tables MASQUERADE rule that
a firewall include adds. masq6 on the wan zone is fw4's way.

Signed-off-by: poqdavid <poq-david@live.com>
dhcp.vaplan.ra_flags gets managed-config beside odhcpd's default
other-config. Clients that do DHCPv6, Windows and Linux among them, then
take an address from it beside SLAAC's, so a static lease's IPv6 suffix
reaches them; with other-config alone they ask it for DNS only. Android
never asks and keeps SLAAC. Set on every start, like the other keys.

Signed-off-by: poqdavid <poq-david@live.com>
How-It-Works says the router advertisements carry the managed and
other-config flags, and what that gives Windows and Linux clients.

Signed-off-by: poqdavid <poq-david@live.com>
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