]> git.ozlabs.org Git - ppp.git/commitdiff
ipv6cp: Fix enforcing peer IPv6 interface identifier (#281)
authorpali <7141871+pali@users.noreply.github.com>
Sat, 19 Jun 2021 01:01:58 +0000 (03:01 +0200)
committerGitHub <noreply@github.com>
Sat, 19 Jun 2021 01:01:58 +0000 (11:01 +1000)
Enforcing peer IPv6 interface identifier is broken in the same way as it
was broken for peer IPv4 address prior commit 9fe8923419a9 ("pppd: Fix
enforcing peer IP address").

IPv6 test case:

    ./pppd noauth asyncmap 0 default-asyncmap novj noaccomp nopcomp nodeflate nobsdcomp nomagic  local nolock nodetach  noip  ipv6 ::2,::1  debug pty "./pppd noauth asyncmap 0 default-asyncmap novj noaccomp nopcomp nodeflate nobsdcomp nomagic  local nolock nodetach  noip  ipv6 ::1:1,::1:2  notty"

Without this patch output from first pppd is:

    sent [IPV6CP ConfReq id=0x5 <addr fe80::0000:0000:0000:0002>]
    rcvd [IPV6CP ConfReq id=0x5 <addr fe80::0000:0000:0001:0001>]
    sent [IPV6CP ConfNak id=0x5 <addr fe80::0000:0000:0000:0001>]
    rcvd [IPV6CP ConfNak id=0x5 <addr fe80::0000:0000:0001:0002>]
    sent [IPV6CP ConfReq id=0x6]
    rcvd [IPV6CP ConfReq id=0x6]
    sent [IPV6CP ConfAck id=0x6]
    rcvd [IPV6CP ConfAck id=0x6]
    local  LL address fe80::0000:0000:0000:0002
    remote LL address fe80::0000:0000:0000:0001

And system configured IPv6 addresses as:

    124: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 3
        link/ppp
        inet6 fe80::2 peer fe80::1/128 scope link nodad
           valid_lft forever preferred_lft forever
    125: ppp1: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 3
        link/ppp
        inet6 fe80::1:1 peer fe80::1:2/128 scope link nodad
           valid_lft forever preferred_lft forever

So both pppd use different IPv6 LL addresses and therefore IPv6 connection
is totally broken between these pppd instances.

With this patch output from first pppd is:

    sent [IPV6CP ConfReq id=0x5 <addr fe80::0000:0000:0000:0002>]
    rcvd [IPV6CP ConfReq id=0x5 <addr fe80::0000:0000:0001:0001>]
    sent [IPV6CP ConfNak id=0x5 <addr fe80::0000:0000:0000:0001>]
    rcvd [IPV6CP ConfNak id=0x5 <addr fe80::0000:0000:0001:0002>]
    sent [IPV6CP ConfReq id=0x6]
    rcvd [IPV6CP ConfReq id=0x6]
    sent [IPV6CP ConfAck id=0x6]
    rcvd [IPV6CP ConfAck id=0x6]
    Peer refused to agree to his interface identifier
    sent [IPV6CP TermReq id=0x7 "Refused his interface identifier"]
    rcvd [IPV6CP TermReq id=0x7 "Refused his interface identifier"]
    sent [IPV6CP TermAck id=0x7]
    rcvd [IPV6CP TermAck id=0x7]
    sent [LCP TermReq id=0x2 "No network protocols running"]
    rcvd [LCP TermAck id=0x2]
    Connection terminated.
    Connect time 0.0 minutes.
    Sent 148 bytes, received 148 bytes.

Now pppd correctly detected that IPv6 interface identifiers negotiation
failed and closed IPv6 connection.

Signed-off-by: Pali Rohár <pali@kernel.org>
pppd/ipv6cp.c

index d80ae216814e9017e65e629aaf15d038d61e4c39..d8b86914fdf3314f4225d6ac4ba72567ebb8d27a 100644 (file)
@@ -943,8 +943,7 @@ ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree)
                break;
            }
            if (!eui64_iszero(wo->hisid) && !wo->accept_remote &&
-               !eui64_equals(ifaceid, wo->hisid) && 
-               eui64_iszero(go->hisid)) {
+               !eui64_equals(ifaceid, wo->hisid)) {
                    
                orc = CONFNAK;
                ifaceid = wo->hisid;
@@ -1200,6 +1199,12 @@ ipv6cp_up(fsm *f)
     /*
      * We must have a non-zero LL address for both ends of the link.
      */
+
+    if (!eui64_iszero(wo->hisid) && !wo->accept_remote && (!ho->neg_ifaceid || !eui64_equals(ho->hisid, wo->hisid))) {
+       error("Peer refused to agree to his interface identifier");
+       ipv6cp_close(f->unit, "Refused his interface identifier");
+       return;
+    }
     if (!ho->neg_ifaceid)
        ho->hisid = wo->hisid;