Odhcp6c issue with my ISP's configuration

Hello,

My current ISP announces two prefixes through ICMPv6 RAs. Both of them have different prefixes announced through ND_OPT_PREFIX_INFORMATION ( https://www.ietf.org/rfc/rfc3542.txt ), which is fine, as odhcp6c will store these in separate entries.
However, they also have different reachable times announced through nd_router_advert.nd_ra_reachable ( https://www.ietf.org/rfc/rfc3542.txt ) and odhcp6c stores these in a single global variable (ra_reachable). Since my ISP sends these ICMPv6 every three seconds and one overrides the other, ra_holdoff is ignored and the dhcpv6.script is called twice every 3 seconds, causing a significant saturation on my weak TP-Link Archer C6 v2 (US) CPU.

In order to solve this issue for my specific case, I've recompiled odhcp6c with the following data not triggering a script call: https://github.com/openwrt/odhcp6c/blob/bcd283632ac13391aac3ebdd074d1fd832d76fa3/src/ra.c#L444-L449 and https://github.com/openwrt/odhcp6c/blob/bcd283632ac13391aac3ebdd074d1fd832d76fa3/src/ra.c#L455
By themselves, they cannot be separated into unique entries, but for me, they only appear together with other options that can, and those can trigger script calls that honor ra_holdoff.

I understand the solution above is very hacky and not a proper one, but I am not a DHCPv6 expert and it's hopeless to contact my ISP and ask them to fix their configuration.
Posting this in the hopes that more knowledgeable DHCPv6 developers can come up with a better solution.

1 Like

These are the changes I made to odhcp6c (ra.c):

@@ -290,7 +290,7 @@

 static bool ra_set_hoplimit(int val)
 {
-       if (val > 0 && val != ra_hoplimit) {
+       if (val > ra_hoplimit) {
                ra_hoplimit = val;
                return true;
        }
@@ -300,7 +300,7 @@

 static bool ra_set_mtu(int val)
 {
-       if (val >= 1280 && val <= 65535 && ra_mtu != val) {
+       if (val >= 1280 && val <= 65535 && (ra_mtu < 1280 || ra_mtu > 65535 || val < ra_mtu)) {
                ra_mtu = val;
                return true;
        }
@@ -310,7 +310,7 @@

 static bool ra_set_reachable(int val)
 {
-       if (val > 0 && val <= 3600000 && ra_reachable != val) {
+       if (val <= 3600000 && val > ra_reachable) {
                ra_reachable = val;
                return true;
        }
@@ -320,7 +320,7 @@

 static bool ra_set_retransmit(int val)
 {
-       if (val > 0 && val <= 60000 && ra_retransmit != val) {
+       if (val <= 60000 && val > ra_retransmit) {
                ra_retransmit = val;
                return true;
        }

Maybe raise an issue on Github: https://github.com/openwrt/odhcp6c ?

I don't really use github nor do I have an account there. Also, there doesn't seem to have any activity from the maintainers for over a year.

On top of the problem described in the OP, my ISP, in their infinite wisdom, has decided to break IPv6 by dropping all packets at my edge gateway, if their source addresses come from prefixes announced through Router Advertisements.
This not only broke odhcp6c, but also my Linux and Windows desktop PCs lost IPv6 connectivity by using one of the RA addresses as the system-wide default IPv6 address (this happens when they are connected directly to the bridged cable modem).

Trying to get my ISP to fix this is a waste of time; it's either automated "tech" support or stupid telemarketing types that don't even know what IPv6 is.

For the time being, as a dirty fix that "solves" both issues, I've removed router-advertisement from the list of accepted ICMPv6 types in the Allow-ICMPv6-Input traffic rule. IPv6 address and prefix is obtained solely by a explicit request from odhcp6c (configuration options reqaddress and reqprefix).

If you are from Brazil and is reading this, STAY AWAY from Claro/NET, you will thank me later.