From: pali <7141871+pali@users.noreply.github.com> Date: Mon, 26 Jul 2021 06:47:57 +0000 (+0200) Subject: pppd: Fix IPv6 compatibility with older kernel versions (#301) X-Git-Tag: ppp-2.5.0~65 X-Git-Url: https://git.ozlabs.org/?a=commitdiff_plain;h=49e1aff19a7ba4376b2a8387f11ff92382cef34f;p=ppp.git pppd: Fix IPv6 compatibility with older kernel versions (#301) Linux kernel versions prior 3.11 do not support setting IPv6 peer addresses. On error try fallback to old IOCTL method. Signed-off-by: Pali Rohár --- diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index 8d6eee9..8f4f2a7 100644 --- a/pppd/sys-linux.c +++ b/pppd/sys-linux.c @@ -3013,7 +3013,14 @@ static int sif6addr_rtnetlink(unsigned int iface, eui64_t our_eui64, eui64_t his /* error == 0 indicates success, negative value is errno code */ if (nlresp.nlerr.error != 0) { - error("sif6addr_rtnetlink: %s (line %d)", strerror(-nlresp.nlerr.error), __LINE__); + /* + * Linux kernel versions prior 3.11 do not support setting IPv6 peer + * addresses and error response is expected. On older kernel versions + * do not show this error message. On error pppd tries to fallback to + * the old IOCTL method. + */ + if (kernel_version >= KVERSION(3,11,0)) + error("sif6addr_rtnetlink: %s (line %d)", strerror(-nlresp.nlerr.error), __LINE__); return 0; } @@ -3029,6 +3036,7 @@ int sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64) struct in6_ifreq ifr6; struct ifreq ifr; struct in6_rtmsg rt6; + int ret; if (sock6_fd < 0) { errno = -sock6_fd; @@ -3044,8 +3052,16 @@ int sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64) if (kernel_version >= KVERSION(2,1,16)) { /* Set both local address and remote peer address (with route for it) via rtnetlink */ - return sif6addr_rtnetlink(ifr.ifr_ifindex, our_eui64, his_eui64); + ret = sif6addr_rtnetlink(ifr.ifr_ifindex, our_eui64, his_eui64); } else { + ret = 0; + } + + /* + * Linux kernel versions prior 3.11 do not support setting IPv6 peer address + * via rtnetlink. So if sif6addr_rtnetlink() fails then try old IOCTL method. + */ + if (!ret) { /* Local interface */ memset(&ifr6, 0, sizeof(ifr6)); IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64);