From 93fd8a0916ef6bc2a33b76bf165a847355343693 Mon Sep 17 00:00:00 2001 From: pali <7141871+pali@users.noreply.github.com> Date: Sat, 19 Jun 2021 03:03:14 +0200 Subject: [PATCH] ipv6cp: Fix enforcing local and peer non-random IPv6 interface identifiers (#283) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit In some cases peer may reject our local IPv6 identifier or may send to us IPV6CP request without any IPv6 identifier or send empty IPv6 identifier (asking as to generate some identifier for him). In these special cases pppd always generated some new random IPv6 identifier and completely ignored the fact that user may already specified IPv6 link local address (used for IPv6 identifier) either at command line or in config file. So properly check pppd options and generate new random IPv6 identifier only in case user did not supply any IPv6 link local address. If pppd was configured to not allow random identifiers and peer rejected our enforced identifiers then pppd connection should be terminated. Signed-off-by: Pali Rohár --- pppd/ipv6cp.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/pppd/ipv6cp.c b/pppd/ipv6cp.c index fef147a..ef03e10 100644 --- a/pppd/ipv6cp.c +++ b/pppd/ipv6cp.c @@ -720,7 +720,9 @@ ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) NAKCIIFACEID(CI_IFACEID, neg_ifaceid, if (treat_as_reject) { try.neg_ifaceid = 0; - } else if (go->accept_local) { + } else if (go->accept_local && !eui64_iszero(ifaceid) && !eui64_equals(ifaceid, go->hisid)) { + try.ourid = ifaceid; + } else if (eui64_iszero(ifaceid) && !go->opt_local) { while (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->hisid)) /* bad luck */ eui64_magic(ifaceid); @@ -772,11 +774,15 @@ ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) goto bad; try.neg_ifaceid = 1; eui64_get(ifaceid, p); - if (go->accept_local) { + if (go->accept_local && !eui64_iszero(ifaceid) && !eui64_equals(ifaceid, go->hisid)) { + try.ourid = ifaceid; + } else if (eui64_iszero(ifaceid) && !go->opt_local) { while (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->hisid)) /* bad luck */ eui64_magic(ifaceid); try.ourid = ifaceid; + } else { + try.neg_ifaceid = 0; } no.neg_ifaceid = 1; break; @@ -955,9 +961,17 @@ ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) orc = CONFNAK; if (eui64_iszero(go->hisid)) /* first time, try option */ ifaceid = wo->hisid; - while (eui64_iszero(ifaceid) || - eui64_equals(ifaceid, go->ourid)) /* bad luck */ - eui64_magic(ifaceid); + if (eui64_equals(ifaceid, go->ourid)) /* bad luck */ + eui64_zero(ifaceid); + if (eui64_iszero(ifaceid)) { + if (wo->opt_remote) + ifaceid = wo->hisid; + else { + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->ourid)) /* bad luck */ + eui64_magic(ifaceid); + } + } go->hisid = ifaceid; DECPTR(sizeof(ifaceid), p); eui64_put(ifaceid, p); -- 2.39.2