Bug 195197 - [netinet6] ipv6 prefix not renewed when managed by userspace daemon with pltime and vltime
Summary: [netinet6] ipv6 prefix not renewed when managed by userspace daemon with plti...
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-net mailing list
URL:
Keywords: patch
Depends on:
Blocks:
 
Reported: 2014-11-20 00:04 UTC by guyyur
Modified: 2018-05-12 18:31 UTC (History)
2 users (show)

See Also:


Attachments
Change prelist_update to be usable by SIOCAIFADDR_IN6 (17.38 KB, patch)
2014-11-20 00:04 UTC, guyyur
no flags Details | Diff
Change prelist_update to be usable by SIOCAIFADDR_IN6 (not wrapped to 80 columns) (17.25 KB, patch)
2014-11-20 00:05 UTC, guyyur
no flags Details | Diff
Add in6_prelist_update function for SIOCAIFADDR_IN6 (3.40 KB, patch)
2014-11-20 00:06 UTC, guyyur
no flags Details | Diff
ndp -P panic (473 bytes, patch)
2018-03-31 23:42 UTC, Mark Johnston
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description guyyur 2014-11-20 00:04:52 UTC
Created attachment 149617 [details]
Change prelist_update to be usable by SIOCAIFADDR_IN6

When refreshing an existing ipv6 address pltime and vltime using SIOCAIFADDR_IN6 the prefix lifetime is not updated.

Issue seen on 11.0-CURRENT r271879M with dhcpcd 6.4.3.
My ISP is providing a prefix with a lifetime of 86400 seconds.
dhcpcd uses SIOCAIFADDR_IN6 to update the address with pltime and vltime.
The address lifetime gets refreshed on renewals but the prefix lifetime is not updated so it expires and the route for the prefix gets deleted.

Attaching several patches trying to solve the problem in different ways.
In both cases, if the prefix exists it will be refreshed.
In case of several addresses for same prefix and different times, prefix time will be from the last one.

1. prelist_update.patch and prelist_update_long_lines.patch
   Change prelist_update so it can be used by both RA and SIOCAIFADDR_IN6.
   prelist_update_long_lines.patch keeps the long lines for smaller diff.
   prelist_update.patch wraps to 80 columns.

2. Add a separate function in6_prelist_update duplicating some of the code from prelist_update but doing less work than prelist_update.


Possible to reproduce with ifconfig and two addresses with the same prefix.
ifconfig -L lan0 inet6 2001:DB8::1 pltime 60 vltime 60
repeat
  ifconfig -L lan0 inet6 2001:DB8::2 pltime 1000 vltime 1000

Checking "ndp -p" after 60 seconds will show the prefix 2001:DB8::/64 as expired.


With dhcpcd:
Before:

# netstat -rn -f inet6
WWWW:XXXX:YYYY:ZZZZ::/64           link#1                        U          lan0
WWWW:XXXX:YYYY:ZZZZ::1             link#1                        UHS         lo0
...


After more than 86400 seconds:

# ifconfig -L lan0 inet6
lan0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=8000b<RXCSUM,TXCSUM,VLAN_MTU,LINKSTATE>
        inet6 fe80::AAAA:BBBB:CCCC:DDDD%lan0 prefixlen 64 scopeid 0x1
        inet6 WWWW:XXXX:YYYY:ZZZZ::1 prefixlen 64 pltime 57257 vltime 57257
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>

# ndp -p
WWWW:XXXX:YYYY:ZZZZ::/64 if=lan0
flags=L vltime=0, pltime=0, expired, ref=1
  No advertising router
...

# netstat -rn -f inet6
WWWW:XXXX:YYYY:ZZZZ::1             link#1                        UHS         lo0
...
Comment 1 guyyur 2014-11-20 00:05:57 UTC
Created attachment 149619 [details]
Change prelist_update to be usable by SIOCAIFADDR_IN6 (not wrapped to 80 columns)
Comment 2 guyyur 2014-11-20 00:06:44 UTC
Created attachment 149620 [details]
Add in6_prelist_update function for SIOCAIFADDR_IN6
Comment 3 roy 2016-08-07 21:12:36 UTC
Discovered the same issue on NetBSD.
Taking the route of separating ioctl address/prefix management from RA prefix management, patches towards the end of the thread.
http://mail-index.netbsd.org/tech-net/2016/08/05/msg006044.html

Patch for dhcpcd to workaround the issue here:
http://roy.marples.name/projects/dhcpcd/vpatch?from=bef60c6f8b4da8c2&to=37ca8a2052507e64
(will be in the next dhcpcd release)
Comment 4 guyyur 2018-03-30 09:58:08 UTC
There is an additional problem that SIOCSPFXFLUSH_IN6 will trigger a KASSERT in nd6_prefix_del "prefix %p has referencing addresses" when kernel is built with INVARIANTS and you add a static address by rc.conf or ifconfig.

Example:
ifconfig vtnet0 inet6 2001:db8::1
ndp -P

I removed my old patches.
The NetBSD changes are the correct way and fix both issues.
I am on my second attempt at porting them, need to do further adjustments to get fully working.
Comment 5 guyyur 2018-03-31 20:02:01 UTC
Bug 194485 patch is needed before the NetBSD "Separate ioctl address prefix management from RA prefix management" changes otherwise the interface route generated by the address won't be used for address neighbor matching.

Changes to add RTF_CONNECTED are also needed to get routes added by dhcpcd 7.0.2 working.
dhcpcd adds the interface route with RTF_STATIC but the patch in bug 194485 currently checks RTF_STATIC is not set (because there is no RTF_CONNECTED) so the address neighbor matching will still not work.

My WIP with bug 194485 and "Separate ioctl address prefix management from RA prefix management" ported over to 12-CURRENT but missing RTF_CONNECTED:
https://github.com/guyyur/freebsd/tree/fix_ipv6_address_prefix
Comment 6 Mark Johnston freebsd_committer 2018-03-31 23:42:04 UTC
Created attachment 192020 [details]
ndp -P panic

(In reply to guyyur from comment #4)
The attached minimal patch ought to address this. SIOCSPFXFLUSH_IN6 ought to leave the associated prefix alone in your example, I believe.
Comment 7 guyyur 2018-04-01 17:58:22 UTC
It fixes the example but there is another scenario that still panics.

# set static ula so can access host even if router is down
ifconfig vtnet0 inet6 fdXX:: eui64

# enable accept_rtadv to learn global address via ra
# rtadvd set to publish fdXX:: so learns ula prefix via ra too
ifconfig vtnet0 inet6 accept_rtadv

# request ra to learn the prefixes from the router
rtsol vtnet0

# flush
ndp -P

In this scenario, when learning fdXX:: prefix via ra it will set ndpr_advrtrs but the prefix is associated with an address without IN6_IFF_AUTOCONF so the address won't be purged.
Comment 8 guyyur 2018-05-12 18:31:04 UTC
I created phabricator D15406 as my attempt
to port the NetBSD changes to 12.0-CURRENT.

Fix for 194485 is needed first.
My attempts for fixes to that bug are D15404 and D15405.