fix parsing of protocol rej
[l2tpns.git] / ppp.c
diff --git a/ppp.c b/ppp.c
index 5af3cb2..005d42a 100644 (file)
--- a/ppp.c
+++ b/ppp.c
@@ -1,6 +1,6 @@
 // L2TPNS PPP Stuff
 
-char const *cvs_id_ppp = "$Id: ppp.c,v 1.68 2005/08/10 11:25:56 bodea Exp $";
+char const *cvs_id_ppp = "$Id: ppp.c,v 1.76 2005/08/29 03:21:14 bodea Exp $";
 
 #include <stdio.h>
 #include <string.h>
@@ -85,8 +85,7 @@ void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                LOG(3, s, t, "PAP login %s/%s\n", user, pass);
        }
 
-       r = radiusnew(s);
-       if (session[s].ip || !r)
+       if (session[s].ip || !(r = radiusnew(s)))
        {
                // respond now, either no RADIUS available or already authenticated
                uint8_t b[MAXCONTROL];
@@ -148,13 +147,6 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
        CSTAT(processchap);
 
        LOG_HEX(5, "CHAP", p, l);
-       r = sess_local[s].radius;
-       if (!r)
-       {
-               LOG(1, s, t, "Unexpected CHAP message\n");
-               STAT(tunnel_rx_errors);
-               return;
-       }
 
        if (l < 4)
        {
@@ -181,6 +173,13 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                return;
        }
 
+       r = sess_local[s].radius;
+       if (!r)
+       {
+               LOG(3, s, t, "Unexpected CHAP message\n");
+               return;
+       }
+
        if (session[s].ppp.phase != Authenticate)
        {
                LOG(2, s, t, "CHAP ignored in %s phase\n", ppp_phase(session[s].ppp.phase));
@@ -341,6 +340,8 @@ void lcp_open(sessionidt s, tunnelidt t)
        // transition to Authentication or Network phase: 
        session[s].ppp.phase = sess_local[s].lcp_authtype ? Authenticate : Network;
 
+       LOG(3, s, t, "LCP: Opened, phase %s\n", ppp_phase(session[s].ppp.phase));
+
        // LCP now Opened
        change_state(s, lcp, Opened);
 
@@ -426,7 +427,7 @@ static uint8_t *ppp_nak(sessionidt s, uint8_t *buf, size_t blen, uint16_t mtype,
                if (!queued)
                        return 0;
 
-               *nak_sent++;
+               (*nak_sent)++;
                *queued = ConfigNak;
                queued += 4;
        }
@@ -472,15 +473,15 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
        if (session[s].die) // going down...
                return;
 
+       LOG(*p == EchoReq ? 4 : 3, s, t, "LCP: recv %s\n", ppp_code(*p));
+       if (config->debug > 3) dumplcp(p, l);
+
        if (*p == ConfigAck)
        {
                int x = l - 4;
                uint8_t *o = (p + 4);
                int authtype = 0;
 
-               LOG(3, s, t, "LCP: ConfigAck (%d bytes)...\n", l);
-               if (config->debug > 3) dumplcp(p, l);
-
                while (x > 2)
                {
                        int type = o[0];
@@ -540,9 +541,6 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                static uint8_t asyncmap[4] = { 0, 0, 0, 0 }; // all zero
                static uint8_t authproto[5];
 
-               LOG(3, s, t, "LCP: ConfigReq (%d bytes)...\n", l);
-               if (config->debug > 3) dumplcp(p, l);
-
                while (x > 2)
                {
                        int type = o[0];
@@ -559,7 +557,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                                        if (!ntohl(*(uint32_t *)(o + 2))) // all bits zero is OK
                                                break;
 
-                                       LOG(2, s, t, "    Remote requesting asyncmap.  Rejecting.\n");
+                                       LOG(3, s, t, "    Remote requesting asyncmap.  Rejecting.\n");
                                        q = ppp_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, asyncmap, sizeof(asyncmap));
                                        break;
 
@@ -593,7 +591,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                                                else
                                                        sprintf(proto_name, "%#4.4x", proto);
 
-                                               LOG(2, s, t, "    Remote requesting %s authentication.  Rejecting.\n", proto_name);
+                                               LOG(3, s, t, "    Remote requesting %s authentication.  Rejecting.\n", proto_name);
 
                                                alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authprefer);
                                                if (alen < 2) break; // paranoia
@@ -622,7 +620,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                                        break;
 
                                default: // Reject any unknown options
-                                       LOG(2, s, t, "    Rejecting PPP LCP Option type %d\n", type);
+                                       LOG(3, s, t, "    Rejecting unknown PPP LCP option %d\n", type);
                                        q = ppp_rej(s, b, sizeof(b), PPPLCP, &response, q, p, o);
                        }
                        x -= length;
@@ -691,7 +689,9 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                        return;
                }
 
-               LOG(3, s, t, "LCP: Sending %s\n", ppp_code(*response));
+               LOG(3, s, t, "LCP: send %s\n", ppp_code(*response));
+               if (config->debug > 3) dumplcp(response, l);
+
                tunnelsend(b, l + (response - b), t);
        }
        else if (*p == ConfigNak)
@@ -700,9 +700,6 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                uint8_t *o = (p + 4);
                int authtype = -1;
 
-               LOG(3, s, t, "LCP: ConfigNak (%d bytes)...\n", l);
-               if (config->debug > 3) dumplcp(p, l);
-
                while (x > 2)
                {
                        int type = o[0];
@@ -769,6 +766,10 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                                if (!response) return;
                                *response = TerminateAck;
                                *((uint16_t *) (response + 2)) = htons(l = 4);
+
+                               LOG(3, s, t, "LCP: send %s\n", ppp_code(*response));
+                               if (config->debug > 3) dumplcp(response, l);
+
                                tunnelsend(b, l + (response - b), t);
                        }
                        break;
@@ -796,10 +797,13 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
        }
        else if (*p == TerminateReq)
        {
-               LOG(3, s, t, "LCP: Received TerminateReq.  Sending TerminateAck\n");
                *p = TerminateAck;      // close
                q = makeppp(b, sizeof(b),  p, l, s, t, PPPLCP);
                if (!q) return;
+
+               LOG(3, s, t, "LCP: send %s\n", ppp_code(*q));
+               if (config->debug > 3) dumplcp(q, l);
+
                tunnelsend(b, l + (q - b), t); // send it
                sessionshutdown(s, "Remote end closed connection.", 3, 0);
        }
@@ -809,25 +813,38 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
        }
        else if (*p == ProtocolRej)
        {
-               if (*(uint16_t *) (p+4) == htons(PPPIPV6CP))
+               uint16_t proto = 0;
+
+               if (l > 4)
+               {
+                       proto = *(p+4);
+                       if (l > 5 && !(proto & 1))
+                       {
+                               proto <<= 8;
+                               proto |= *(p+5);
+                       }
+               }
+
+               if (proto == PPPIPV6CP)
                {
                        LOG(3, s, t, "IPv6 rejected\n");
                        change_state(s, ipv6cp, Closed);
                }
                else
                {
-                       LOG(1, s, t, "Unexpected LCP protocol reject 0x%X\n",
-                               ntohs(*(uint16_t *) (p+4)));
-                       STAT(tunnel_rx_errors);
+                       LOG(3, s, t, "LCP protocol reject: 0x%04X\n", proto);
                }
        }
        else if (*p == EchoReq)
        {
-               LOG(5, s, t, "LCP: Received EchoReq.  Sending EchoReply\n");
                *p = EchoReply;         // reply
                *(uint32_t *) (p + 4) = htonl(session[s].magic); // our magic number
                q = makeppp(b, sizeof(b), p, l, s, t, PPPLCP);
                if (!q) return;
+
+               LOG(4, s, t, "LCP: send %s\n", ppp_code(*q));
+               if (config->debug > 3) dumplcp(q, l);
+
                tunnelsend(b, l + (q - b), t); // send it
        }
        else if (*p == EchoReply)
@@ -847,7 +864,10 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                q = makeppp(b, sizeof(b), p, l, s, t, PPPLCP);
                if (!q) return;
 
-               LOG(3, s, t, "Unexpected LCP code %s\n", ppp_code(code));
+               LOG(2, s, t, "Unexpected LCP code %s\n", ppp_code(code));
+               LOG(3, s, t, "LCP: send %s\n", ppp_code(*q));
+               if (config->debug > 3) dumplcp(q, l);
+
                tunnelsend(b, l + (q - b), t);
        }
 }
@@ -904,6 +924,8 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                return;
        }
 
+       LOG(3, s, t, "IPCP: recv %s\n", ppp_code(*p));
+
        if (*p == ConfigAck)
        {
                switch (session[s].ppp.ipcp)
@@ -936,8 +958,6 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                int gotip = 0;
                in_addr_t addr;
 
-               LOG(3, s, t, "IPCP: ConfigReq received\n");
-
                while (length > 2)
                {
                        switch (*o)
@@ -949,8 +969,9 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                                addr = htonl(session[s].ip);
                                if (memcmp(o + 2, &addr, (sizeof addr)))
                                {
+                                       uint8_t *oq = q;
                                        q = ppp_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr));
-                                       if (!q || *response == ConfigRej)
+                                       if (!q || (q != oq && *response == ConfigRej))
                                        {
                                                sessionshutdown(s, "Can't negotiate IPCP.", 3, 0);
                                                return;
@@ -1061,15 +1082,15 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                        return;
                }
 
-               LOG(3, s, t, "IPCP: Sending %s\n", ppp_code(*response));
+               LOG(3, s, t, "IPCP: send %s\n", ppp_code(*response));
                tunnelsend(b, l + (response - b), t);
        }
        else if (*p == TerminateReq)
        {
-               LOG(3, s, t, "IPCP: Received TerminateReq.  Sending TerminateAck\n");
                *p = TerminateAck;
                q = makeppp(b, sizeof(b), p, l, s, t, PPPIPCP);
                if (!q) return;
+               LOG(3, s, t, "IPCP: send %s\n", ppp_code(*q));
                tunnelsend(b, l + (q - b), t);
                change_state(s, ipcp, Stopped);
        }
@@ -1086,7 +1107,8 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                q = makeppp(b, sizeof(b), p, l, s, t, PPPIPCP);
                if (!q) return;
 
-               LOG(3, s, t, "Unexpected IPCP code %s\n", ppp_code(code));
+               LOG(2, s, t, "Unexpected IPCP code %s\n", ppp_code(code));
+               LOG(3, s, t, "IPCP: send %s\n", ppp_code(*q));
                tunnelsend(b, l + (q - b), t);
        }
 }
@@ -1134,6 +1156,8 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                return;
        }
 
+       LOG(3, s, t, "IPV6CP: recv %s\n", ppp_code(*p));
+
        if (!config->ipv6_prefix.s6_addr[0])
        {
                LOG(2, s, t, "IPV6CP: %s rejected (not configured)\n", ppp_code(*p));
@@ -1182,8 +1206,6 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                int gotip = 0;
                uint8_t ident[8];
 
-               LOG(3, s, t, "IPV6CP: ConfigReq received\n");
-
                while (length > 2)
                {
                        switch (*o)
@@ -1281,15 +1303,15 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                        return;
                }
 
-               LOG(3, s, t, "IPV6CP: Sending %s\n", ppp_code(*response));
+               LOG(3, s, t, "IPV6CP: send %s\n", ppp_code(*response));
                tunnelsend(b, l + (response - b), t);
        }
        else if (*p == TerminateReq)
        {
-               LOG(3, s, t, "IPV6CP: Received TerminateReq.  Sending TerminateAck\n");
                *p = TerminateAck;
                q = makeppp(b, sizeof(b),  p, l, s, t, PPPIPV6CP);
                if (!q) return;
+               LOG(3, s, t, "IPV6CP: send %s\n", ppp_code(*q));
                tunnelsend(b, l + (q - b), t);
                change_state(s, ipv6cp, Stopped);
        }
@@ -1306,7 +1328,8 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                q = makeppp(b, sizeof(b), p, l, s, t, PPPIPV6CP);
                if (!q) return;
 
-               LOG(3, s, t, "Unexpected IPV6CP code %s\n", ppp_code(code));
+               LOG(2, s, t, "Unexpected IPV6CP code %s\n", ppp_code(code));
+               LOG(3, s, t, "IPV6CP: send %s\n", ppp_code(*q));
                tunnelsend(b, l + (q - b), t);
        }
 }
@@ -1556,6 +1579,7 @@ void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                STAT(tunnel_rx_errors);
        }
 
+       LOG(3, s, t, "CCP: recv %s\n", ppp_code(*p));
        if (*p == ConfigAck)
        {
                switch (session[s].ppp.ccp)
@@ -1640,15 +1664,15 @@ void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                        return;
                }
 
-               LOG(3, s, t, "CCP: Sending %s\n", ppp_code(*q));
+               LOG(3, s, t, "CCP: send %s\n", ppp_code(*q));
                tunnelsend(b, l + (q - b), t);
        }
        else if (*p == TerminateReq)
        {
-               LOG(3, s, t, "CCP: Received TerminateReq.  Sending TerminateAck\n");
                *p = TerminateAck;
                q = makeppp(b, sizeof(b),  p, l, s, t, PPPCCP);
                if (!q) return;
+               LOG(3, s, t, "CCP: send %s\n", ppp_code(*q));
                tunnelsend(b, l + (q - b), t);
                change_state(s, ccp, Stopped);
        }
@@ -1665,7 +1689,8 @@ void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                q = makeppp(b, sizeof(b), p, l, s, t, PPPCCP);
                if (!q) return;
 
-               LOG(3, s, t, "Unexpected CCP code %s\n", ppp_code(code));
+               LOG(2, s, t, "Unexpected CCP code %s\n", ppp_code(code));
+               LOG(3, s, t, "CCP: send %s\n", ppp_code(*q));
                tunnelsend(b, l + (q - b), t);
        }
 }
@@ -1792,9 +1817,10 @@ void sendlcp(sessionidt s, tunnelidt t, int authtype)
        if (!(q = makeppp(b, sizeof(b), NULL, 0, s, t, PPPLCP)))
                return;
 
-       LOG(4, s, t, "Sending LCP ConfigReq%s%s\n",
-           authtype ? " for " : "",
-           authtype ? (authtype == AUTHCHAP ? "CHAP" : "PAP") : "");
+       LOG(3, s, t, "LCP: send ConfigReq%s%s%s\n",
+           authtype ? " (" : "",
+           authtype ? (authtype == AUTHCHAP ? "CHAP" : "PAP") : "",
+           authtype ? ")" : "");
 
        if (!session[s].mru)
                session[s].mru = DEFAULT_MRU;
@@ -1818,6 +1844,8 @@ void sendlcp(sessionidt s, tunnelidt t, int authtype)
        *(uint16_t *)(q + 2) = htons(l - q); // Length
 
        LOG_HEX(5, "PPPLCP", q, l - q);
+       if (config->debug > 3) dumplcp(q, l - q);
+
        tunnelsend(b, (l - b), t);
 }
 
@@ -1829,7 +1857,8 @@ void sendccp(sessionidt s, tunnelidt t)
        if (!(q = makeppp(b, sizeof(b), NULL, 0, s, t, PPPCCP)))
                return;
 
-       LOG(4, s, t, "Sending CCP ConfigReq for no compression\n");
+       LOG(3, s, t, "CCP: send ConfigReq (no compression)\n");
+
        *q = ConfigReq;
        *(uint8_t *)(q + 1) = (time_now % 255) + 1; // ID
        *(uint16_t *)(q + 2) = htons(4); // Length