Linux PPP protocol development
 help / color / mirror / Atom feed
* pppd and IPv6 routes
@ 2026-04-13 12:37 Mikulas Patocka
  2026-04-25  0:27 ` Benjamin Cama
  0 siblings, 1 reply; 2+ messages in thread
From: Mikulas Patocka @ 2026-04-13 12:37 UTC (permalink / raw)
  To: linux-ppp

Hi

I have a problem with pppd and IPv6. I use pppd 2.4.9 from Debian 12.

I get this ppp0 device from my ISP (using ppp-over-ethernet):
23: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1492 state UNKNOWN qlen 3
    inet6 2a00:1028:8391:4349:4839:8541:daa4:adcf/64 scope global dynamic mngtmpaddr
       valid_lft 86287sec preferred_lft 3487sec
    inet6 fe80::4839:8541:daa4:adcf peer fe80::e681:84ff:fec2:4b34/128 scope link
       valid_lft forever preferred_lft forever

I run wide-dhcpv6-client, it sends "dhcp6 solicit" to "ff02::1:2":
fe80::4839:8541:daa4:adcf.dhcpv6-client > ff02::1:2.dhcpv6-server: dhcp6 solicit
I receive dhcp6 advertise from the ISP:
e681:84ff:fec2:4b34.dhcpv6-server > fe80::4839:8541:daa4:adcf.dhcpv6-client: dhcp6 advertise

The problem is that the kernel doesn't pass the packet to the dhcp6c 
daemon, it rejects the packet with a redirect to itself:
fe80::4839:8541:daa4:adcf > fe80::e681:84ff:fec2:4b34: ICMP6, redirect, fe80::4839:8541:daa4:adcf to fe80::4839:8541:daa4:adcf, length 176

According to RFC, redirect to itself means that the sender should send the 
packet to the same interface to a different host.

"ping fe80::e681:84ff:fec2:4b34%ppp0" also doesn't work - tcpdump shows 
that the reply arrives, but the kernel rejects it with a redirect to 
itself.

There are the following routes set up on the ppp0 interface:

anycast 2a00:1028:8391:4349:: dev ppp0 proto kernel metric 0 pref medium
2a00:1028:8391:4349::/64 dev ppp0 proto kernel metric 256 expires 85949sec pref medium
fe80::fe80::4839:8541:daa4:adcf dev ppp0 proto kernel metric 256 pref medium
fe80::e681:84ff:fec2:4b34 dev ppp0 proto kernel metric 256 pref medium
multicast ff00::/8 dev ppp0 proto kernel metric 256 pref medium
default via fe80::e681:84ff:fec2:4b34 dev ppp0 proto ra metric 1024 
expires 4049sec hoplimit 64 pref medium

If I delete the route to "fe80::fe80::4839:8541:daa4:adcf" and add the 
same route with the "local' specifier, the problem is fixed, ping works 
and dhcp6c correctly receives the responses and sets up IPv6 addresses in 
the inner network:

# ip -6 route del fe80::4839:8541:daa4:adcf dev ppp0
# ip -6 route add local fe80::4839:8541:daa4:adcf dev ppp0

So, the question is - why doesn't pppd set the local route as "local"? Is 
it a bug in pppd? Or a bug in the kernel?

I tried to set up the local route in 
/etc/ppp/ipv6-up.d/wide-dhcpv6-client, but it is not reliable, sometimes 
it works and sometimes it doesn't, the script is probably racing with pppd 
setting the routes:

#!/bin/sh
sleep 3
ip -6 route del "$PPP_LOCAL" dev ppp0
ip -6 route add local "$PPP_LOCAL" dev ppp0
systemctl restart wide-dhcpv6-client.service

Mikulas

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: pppd and IPv6 routes
  2026-04-13 12:37 pppd and IPv6 routes Mikulas Patocka
@ 2026-04-25  0:27 ` Benjamin Cama
  0 siblings, 0 replies; 2+ messages in thread
From: Benjamin Cama @ 2026-04-25  0:27 UTC (permalink / raw)
  To: Mikulas Patocka; +Cc: linux-ppp

Hi Mikulas,

Le lundi 13 avril 2026 à 14:37, Mikulas Patocka a écrit :
>I have a problem with pppd and IPv6. I use pppd 2.4.9 from Debian 12.

For reference, on my side I’m also using Debian 12, pppd 2.4.9 and 
kernel version 6.12.22+bpo-amd64.

Also, I’m doing my tests just on a looped back dummy connection, like 
so:

   pppd noauth pty "pppd noauth notty" debug nodetach

I just get link-local addresses, but it’s enough to test.

>I get this ppp0 device from my ISP (using ppp-over-ethernet):
>23: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1492 state UNKNOWN qlen 3
>    inet6 2a00:1028:8391:4349:4839:8541:daa4:adcf/64 scope global dynamic mngtmpaddr
>       valid_lft 86287sec preferred_lft 3487sec
>    inet6 fe80::4839:8541:daa4:adcf peer fe80::e681:84ff:fec2:4b34/128 scope link
>       valid_lft forever preferred_lft forever

Same thing here (but no GUA).

>I run wide-dhcpv6-client, it sends "dhcp6 solicit" to "ff02::1:2":

BTW, WIDE is really an ancient implementation, you may run in some 
strange interaction with recent code.

>fe80::4839:8541:daa4:adcf.dhcpv6-client > ff02::1:2.dhcpv6-server: dhcp6 solicit
>I receive dhcp6 advertise from the ISP:
>e681:84ff:fec2:4b34.dhcpv6-server > fe80::4839:8541:daa4:adcf.dhcpv6-client: dhcp6 advertise

(I did not test DHCPv6)

>The problem is that the kernel doesn't pass the packet to the dhcp6c
>daemon, it rejects the packet with a redirect to itself:
>fe80::4839:8541:daa4:adcf > fe80::e681:84ff:fec2:4b34: ICMP6, redirect, fe80::4839:8541:daa4:adcf to fe80::4839:8541:daa4:adcf, length 176

Quite strange.

>According to RFC, redirect to itself means that the sender should send the
>packet to the same interface to a different host.

I’m not sure where you interpret that from. A redirect is a hint that 
the address is present on the same *link* (not interface), but may be a 
different host or itself, maybe. But in this case, as you clearly see 
the address *is* in fact from this very interface, something very wrong 
is going on.

>"ping fe80::e681:84ff:fec2:4b34%ppp0" also doesn't work - tcpdump shows
>that the reply arrives, but the kernel rejects it with a redirect to
>itself.

By default, in my case, I get ping correctly answered.

>There are the following routes set up on the ppp0 interface:
>
>anycast 2a00:1028:8391:4349:: dev ppp0 proto kernel metric 0 pref medium
>2a00:1028:8391:4349::/64 dev ppp0 proto kernel metric 256 expires 85949sec pref medium
>fe80::fe80::4839:8541:daa4:adcf dev ppp0 proto kernel metric 256 pref medium
>fe80::e681:84ff:fec2:4b34 dev ppp0 proto kernel metric 256 pref medium
>multicast ff00::/8 dev ppp0 proto kernel metric 256 pref medium
>default via fe80::e681:84ff:fec2:4b34 dev ppp0 proto ra metric 1024
>expires 4049sec hoplimit 64 pref medium

Here, an excerpt from my setup, showing routes from all the table as you 
do:

   $ ip -6 r show table all|grep ppp0
   fe80::117e:f5e4:95b7:b93d dev ppp0 proto kernel metric 256 pref medium
   fe80::14af:cf07:dc47:6de5 dev ppp0 proto kernel metric 256 pref medium
   local fe80::117e:f5e4:95b7:b93d dev ppp0 table local proto kernel metric 0 pref medium
   multicast ff00::/8 dev ppp0 table local proto kernel metric 256 pref medium

>If I delete the route to "fe80::fe80::4839:8541:daa4:adcf" and add the
>same route with the "local' specifier, the problem is fixed, ping works
>and dhcp6c correctly receives the responses and sets up IPv6 addresses in
>the inner network:
>
># ip -6 route del fe80::4839:8541:daa4:adcf dev ppp0
># ip -6 route add local fe80::4839:8541:daa4:adcf dev ppp0

And indeed, when I do the opposite (removing the local route), I get a 
redirect like you on ppp0, then the ping response being repeated on ppp0 
many times before hop limit is reached and I get an ICMPv6 time exceeded 
on lo. The kernel does not recognize this address as belonging to 
itself.

So you are on the right track with the missing local route. Note that my 
table output show *two* routes for the host’s link-local address, on 
from the main table *and* one from the local table. I note that your 
table output does not specify table: did you somehow pasted everything 
together in your message, or is this really your output only from the 
main table? In the latter case, something is very wrong if e.g. an 
anycast route shows up here. To show e.g. only the local routing table, 
use "ip route show table local".

>So, the question is - why doesn't pppd set the local route as "local"? Is
>it a bug in pppd? Or a bug in the kernel?

I think the local route is *not* set by pppd, but indeed by the kernel 
itself, for its special local table. But also maybe WIDE dhcp is 
mangling this, I’ve already seen strange behavior with it in a distant 
past.

>I tried to set up the local route in
>/etc/ppp/ipv6-up.d/wide-dhcpv6-client, but it is not reliable, sometimes
>it works and sometimes it doesn't, the script is probably racing with pppd
>setting the routes:
>
>#!/bin/sh
>sleep 3
>ip -6 route del "$PPP_LOCAL" dev ppp0
>ip -6 route add local "$PPP_LOCAL" dev ppp0

In general, you should *not* have to play with local route. I think 
something is wrong either on the kernel side, or with the WIDE dhcp 
client interaction.

Regards.
-- Benjamin

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-04-25 18:00 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-13 12:37 pppd and IPv6 routes Mikulas Patocka
2026-04-25  0:27 ` Benjamin Cama

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox