]> git.ozlabs.org Git - ppp.git/commitdiff
ipv6cp: Fix enforcing local and peer non-random IPv6 interface identifiers (#283)
authorpali <7141871+pali@users.noreply.github.com>
Sat, 19 Jun 2021 01:03:14 +0000 (03:03 +0200)
committerGitHub <noreply@github.com>
Sat, 19 Jun 2021 01:03:14 +0000 (11:03 +1000)
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 <pali@kernel.org>
pppd/ipv6cp.c

index fef147adf260b4eac6e1185aaafe359c1cf0fcf3..ef03e1015503220db596ef2e3045ae5eb65af0df 100644 (file)
@@ -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);