Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FS#2759 - odhcpd IPv6 NDP + macOS don't play together #7561

Open
openwrt-bot opened this issue Jan 21, 2020 · 5 comments
Open

FS#2759 - odhcpd IPv6 NDP + macOS don't play together #7561

openwrt-bot opened this issue Jan 21, 2020 · 5 comments
Labels
core packages pull request/issue for core (in-tree) packages flyspray release/19.07 pull request/issue targeted (also) for OpenWrt 19.07 release

Comments

@openwrt-bot
Copy link

GolDDranks:

My device: TP-Link Archer C7 v2.0 (JP)
My software stack: OpenWrt 19.07

My router uses odhcpd's relay mode to relay IPv6 neighbor discovery protocol and router advertisements from the uplink router.

My linux-based system connected to the router is able to get IPv6 connectivity through the router without problems.

However, my macOS-based system doesn't get IPv6 connectivity. It gets a global IPv6 prefix, which suggests that it's able to receive RA packets, but my router is also unable to ping6 the macOS system by it's globally unique address, and doing ip -6 neigh on the router makes it clear that the router doesn't know the MAC address of the macOS system, and all of it's probes to find it, end up failing.

Inspecting the ICMPv6 traffic in the LAN shows that my macOS system doesn't respond to the neighbor solicitation packets send by the router. Here's an example of such a packet:

02:28:50.006540 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fd26:e9f1:e833::1 > ff02::1:ff65:88f8: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has 2404:7a80:9621:7100:404:978a:5765:88f8
source link-address option (1), length 8 (1): 18:a6:f7:8d:c0:d3

Here, fd26:e9f1:e833::1 is the ULA of the LAN interface of the router.

According to Apple discussion board ( https://discussions.apple.com/thread/8620806 ) macOS seems to have a behaviour such that it ignores neighbor solicitation packets unless the source address of the packet is a link-local address.

Indeed, commenting out option ula_prefix in /etc/config/network makes odhcpd to use link-local addresses, and that makes macOS to respond to neighbor solicitation queries, and in my system, demonstrably restores IPv6 connectivity.

Since macOS is a very common operating system, it would be benefical if odhcpd's default behaviour were to use LLA in NDP packets. The current situation of not being able to set ULA prefix without losing connectivity is unfortunate. (And I think that ULA prefix is set by default in OpenWRT, which makes macOS not play together with it by default.)

For reference, here's a forum thread I documented my forays into inspecting this problem: https://forum.openwrt.org/t/how-to-send-icmp6-neighbor-solicitation-with-a-link-local-source-address/53220

Could the default source address of odhcpd's NDP/RA packets be changed to LLA?

@aparcar aparcar added release/19.07 pull request/issue targeted (also) for OpenWrt 19.07 release core packages pull request/issue for core (in-tree) packages labels Feb 22, 2022
@netprince17
Copy link

I can confirm this behavior from macos. Would be great to have a switch in odhcpd to default to lla instead of ula. (or just use lla by default)

@golddranks
Copy link

Hopefully this will get more attention as IPv6 gets more common.

@stephengroat
Copy link

stephengroat commented Sep 10, 2022

Can confirm this is still an issue for 22.03

Found this while debugging connectivity with T-Mobile's Home Internet offering. When IPv4 uses CGNET, IPv6 can offer significant performance benefits. For macOS users, would be nice if it worked by default

@Dax333
Copy link

Dax333 commented May 17, 2023

Thank you. I've wasted days on this while only using Macs. 22.05

@golddranks
Copy link

I think it's time to do something for this. I am a coder, but not too familiar with Linux system programming. However, here's my attempt of understanding the code failed attempt:

1) It sends NA packets [here](https://github.com/openwrt/odhcpd/blob/master/src/ndp.c#L374), giving an argument `iface`. I suspect this should be an `iface` with an LLA (at least when if there's an enabled option to use LLA), but it ends up being an ULA. 2) Where is the call happening? Here, in `handle_solicit` [handle_solicit](https://github.com/openwrt/odhcpd/blob/master/src/ndp.c#L326C13-L326C27). It, by itself, seems to be a callback, assigned [here](https://github.com/openwrt/odhcpd/blob/master/src/ndp.c#L203C20-L203C32). 3) So, there's an event called `ndp_event`, registered with `odhcpd_register` and the callback is assigned to `handle_dgram`. 4) The only place `handle_dgram` is called, is these two lines [here](https://github.com/openwrt/odhcpd/blob/master/src/odhcpd.c#L408). Note that the first one gives `NULL` as the argument for `iface`. As `handle_solicit` assumes that the argument is not `NULL` (it liberally dereferences it), I deduce it must be the second line `handle_solicit` gets called. My Linux system programming knowledge fails me with what the `addr.nl.nl_family == AF_NETLINK` line checks, maybe come back to that later, if we find ourselves stuck. Also, the log lines are different, so maybe I should try running this and see the log to double check that my assumptions are correct. 5) `avl_for_each_element` has a weird syntax which seems like it's a macro. It's not defined in the repo. C includes be cursed, they are so hard to trace back! However, Google helps: https://lxr.openwrt.org/source/libubox/avl.h#L355 So we can think of it as a iterator loop over a tree. (As suggested by the name, too.) 6) So, it just seems to select an `iface` from all interfaces, that matches `destiface`. `destiface` clearly seems to mean "destination interface", so it seems weird that the log says "from" and not "to". 7) Oops, indeed this is weird. `send_na` must be the function that sends the NA packet upstream, as a response to successful solicitation. Let's try again.

Next try:

  1. It seems to be here where odhcpd constructs and sends a neighbor solicitation message.
  2. iface seems suspicious. According to my tests, setting ULA assigns both ULA and LLA to the same interface, with same interface index (here, 07, meaning br-lan):
# cat /proc/net/if_inet6
24047a80962171000000000000000001 09 40 00 00   eth0.2
24047a80962171000000000066660001 0b 70 00 80   wg_dmz
fe800000000000001aa6f7fffe8dc0d4 02 40 20 80     eth0
fe800000000000001aa6f7fffe8dc0d4 0a 40 20 80   eth0.3
fe800000000000001aa6f7fffe8dc0d4 09 40 20 80   eth0.2
fdff73a47fbc00000000000000000001 07 3c 00 80   br-lan
fe800000000000001aa6f7fffe8dc0d2 0f 40 20 80    wlan0
24047a80962171000000000099990001 0c 70 00 80   wg_lan
00000000000000000000000000000001 01 80 10 80       lo
fe800000000000001aa6f7fffe8dc0d3 0e 40 20 80    wlan1
fe800000000000001aa6f7fffe8dc0d3 07 40 20 80   br-lan
fe800000000000001aa6f7fffe8dc0d3 03 40 20 80     eth1
  1. So, there must be some way, using the netlink and rtnetlink libraries, to specify not only the interface, but the sending address. Currently it seems to be that this choise is just left for the library/kernel. My knowledge of Linux net programming is not enough for make quick progress, so I'll come back to this later after studying netlink/rtnetlink a bit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core packages pull request/issue for core (in-tree) packages flyspray release/19.07 pull request/issue targeted (also) for OpenWrt 19.07 release
Projects
None yet
Development

No branches or pull requests

6 participants