moved protos here from ipcp.h; print reason on terminate-request;
[ppp.git] / pppd / lcp.c
index ec1b911228be5505b0fba9489c4108f2c86b1011..7d0a40677776f1b841e568aaa85a2ce66c364e5e 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: lcp.c,v 1.22 1995/10/27 03:42:09 paulus Exp $";
+static char rcsid[] = "$Id: lcp.c,v 1.26 1996/05/28 00:41:13 paulus Exp $";
 #endif
 
 /*
@@ -38,15 +38,8 @@ static char rcsid[] = "$Id: lcp.c,v 1.22 1995/10/27 03:42:09 paulus Exp $";
 #include "pppd.h"
 #include "fsm.h"
 #include "lcp.h"
-#include "magic.h"
 #include "chap.h"
-#include "upap.h"
-#include "ipcp.h"
-
-#ifdef _linux_         /* Needs ppp ioctls */
-#include <net/if.h>
-#include <linux/if_ppp.h>
-#endif
+#include "magic.h"
 
 /* global vars */
 fsm lcp_fsm[NUM_PPP];                  /* LCP fsm structure (global)*/
@@ -62,11 +55,6 @@ static u_int32_t lcp_echo_timer_running = 0;  /* TRUE if a timer is running */
 
 static u_char nak_buffer[PPP_MRU];     /* where we construct a nak packet */
 
-#ifdef _linux_
-u_int32_t idle_timer_running = 0;
-extern int idle_time_limit;
-#endif
-
 /*
  * Callbacks for fsm code.  (CI = Configuration Information)
  */
@@ -113,6 +101,12 @@ static fsm_callbacks lcp_callbacks = {     /* LCP callback routines */
     "LCP"                      /* String name of protocol */
 };
 
+struct protent lcp_protent = {
+    PPP_LCP, lcp_init, lcp_input, lcp_protrej,
+    lcp_lowerup, lcp_lowerdown, lcp_open, lcp_close,
+    lcp_printpkt, NULL, 1, "LCP", NULL, NULL
+};
+
 int lcp_loopbackfail = DEFLOOPBACKFAIL;
 
 /*
@@ -201,8 +195,9 @@ lcp_open(unit)
  * lcp_close - Take LCP down.
  */
 void
-lcp_close(unit)
+lcp_close(unit, reason)
     int unit;
+    char *reason;
 {
     fsm *f = &lcp_fsm[unit];
 
@@ -210,68 +205,16 @@ lcp_close(unit)
        /*
         * This action is not strictly according to the FSM in RFC1548,
         * but it does mean that the program terminates if you do a
-        * lcp_close(0) in passive/silent mode when a connection hasn't
+        * lcp_close() in passive/silent mode when a connection hasn't
         * been established.
         */
        f->state = CLOSED;
        lcp_finished(f);
 
     } else
-       fsm_close(&lcp_fsm[unit]);
+       fsm_close(&lcp_fsm[unit], reason);
 }
 
-#ifdef _linux_
-static void IdleTimeCheck __P((caddr_t));
-
-/*
- * Timer expired for the LCP echo requests from this process.
- */
-
-static void
-RestartIdleTimer (f)
-    fsm *f;
-{
-    u_long             delta;
-    struct ppp_idle    ddinfo;
-/*
- * Read the time since the last packet was received.
- */
-    if (ioctl (fd, PPPIOCGIDLE, &ddinfo) < 0) {
-        syslog (LOG_ERR, "ioctl(PPPIOCGIDLE): %m");
-        die (1);
-    }
-/*
- * Compute the time since the last packet was received. If the timer
- *  has expired then disconnect the line.
- */
-    delta = idle_time_limit - (u_long) ddinfo.recv_idle;
-    if (((int) delta <= 0L) && (f->state == OPENED)) {
-        syslog (LOG_NOTICE, "No IP frames received within idle time limit");
-       lcp_close(f->unit);             /* Reset connection */
-       phase = PHASE_TERMINATE;        /* Mark it down */
-    } else {
-        if ((int) delta <= 0L)
-           delta = (u_long) idle_time_limit;
-        assert (idle_timer_running==0);
-        TIMEOUT (IdleTimeCheck, (caddr_t) f, delta);
-        idle_timer_running = 1;
-    }
-}
-
-/*
- * IdleTimeCheck - Timer expired on the IDLE detection for IP frames
- */
-
-static void
-IdleTimeCheck (arg)
-    caddr_t arg;
-{
-    if (idle_timer_running != 0) {
-        idle_timer_running = 0;
-        RestartIdleTimer ((fsm *) arg);
-    }
-}
-#endif
 
 /*
  * lcp_lowerup - The lower layer is up.
@@ -282,7 +225,6 @@ lcp_lowerup(unit)
 {
     lcp_options *wo = &lcp_wantoptions[unit];
 
-    sifdown(unit);
     /*
      * Don't use A/C or protocol compression on transmission,
      * but accept A/C and protocol compressed packets
@@ -376,6 +318,8 @@ lcp_rprotrej(f, inp, len)
     u_char *inp;
     int len;
 {
+    int i;
+    struct protent *protp;
     u_short prot;
 
     LCPDEBUG((LOG_INFO, "lcp_rprotrej."));
@@ -402,7 +346,17 @@ lcp_rprotrej(f, inp, len)
        return;
     }
 
-    DEMUXPROTREJ(f->unit, prot);       /* Inform protocol */
+    /*
+     * Upcall the proper Protocol-Reject routine.
+     */
+    for (i = 0; (protp = protocols[i]) != NULL; ++i)
+       if (protp->protocol == prot && protp->enabled_flag) {
+           (*protp->protrej)(f->unit);
+           return;
+       }
+
+    syslog(LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x",
+          prot);
 }
 
 
@@ -940,7 +894,7 @@ lcp_nakci(f, p, len)
        if (looped_back) {
            if (++try.numloops >= lcp_loopbackfail) {
                syslog(LOG_NOTICE, "Serial line is looped back.");
-               lcp_close(f->unit);
+               lcp_close(f->unit, "Loopback detected");
            }
        } else
            try.numloops = 0;
@@ -974,8 +928,6 @@ lcp_rejci(f, p, len)
     u_char cichar;
     u_short cishort;
     u_int32_t cilong;
-    u_char *start = p;
-    int plen = len;
     lcp_options try;           /* options to request next time */
 
     try = *go;
@@ -1080,8 +1032,6 @@ lcp_rejci(f, p, len)
 
 bad:
     LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!"));
-    LCPDEBUG((LOG_WARNING, "lcp_rejci: plen %d len %d off %d",
-             plen, len, p - start));
     return 0;
 }
 
@@ -1104,7 +1054,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
     lcp_options *ho = &lcp_hisoptions[f->unit];
     lcp_options *ao = &lcp_allowoptions[f->unit];
     u_char *cip, *next;                /* Pointer to current and next CIs */
-    u_char cilen, citype, cichar;/* Parsed len, type, char value */
+    int cilen, citype, cichar; /* Parsed len, type, char value */
     u_short cishort;           /* Parsed short value */
     u_int32_t cilong;          /* Parse long value */
     int rc = CONFACK;          /* Final packet return code */
@@ -1135,6 +1085,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
            orc = CONFREJ;              /* Reject bad CI */
            cilen = l;                  /* Reject till end of packet */
            l = 0;                      /* Don't loop again */
+           citype = 0;
            goto endswitch;
        }
        GETCHAR(citype, p);             /* Parse CI type */
@@ -1253,7 +1204,11 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
                    break;
                }
                GETCHAR(cichar, p);     /* get digest type*/
-               if (cichar != ao->chap_mdtype) {
+               if (cichar != CHAP_DIGEST_MD5
+#ifdef CHAPMS
+                   && cichar != CHAP_MICROSOFT
+#endif
+                   ) {
                    orc = CONFNAK;
                    PUTCHAR(CI_AUTHTYPE, nakp);
                    PUTCHAR(CILEN_CHAP, nakp);
@@ -1417,8 +1372,6 @@ endswitch:
 
 /*
  * lcp_up - LCP has come UP.
- *
- * Start UPAP, IPCP, etc.
  */
 static void
 lcp_up(f)
@@ -1455,10 +1408,6 @@ lcp_up(f)
     if (ho->neg_mru)
        peer_mru[f->unit] = ho->mru;
 
-    ChapLowerUp(f->unit);      /* Enable CHAP */
-    upap_lowerup(f->unit);     /* Enable UPAP */
-    ipcp_lowerup(f->unit);     /* Enable IPCP */
-    ccp_lowerup(f->unit);      /* Enable CCP */
     lcp_echo_lowerup(f->unit);  /* Enable echo messages */
 
     link_established(f->unit);
@@ -1477,19 +1426,14 @@ lcp_down(f)
     lcp_options *go = &lcp_gotoptions[f->unit];
 
     lcp_echo_lowerdown(f->unit);
-    ccp_lowerdown(f->unit);
-    ipcp_lowerdown(f->unit);
-    ChapLowerDown(f->unit);
-    upap_lowerdown(f->unit);
 
-    sifdown(f->unit);
+    link_down(f->unit);
+
     ppp_send_config(f->unit, PPP_MRU, 0xffffffff, 0, 0);
     ppp_recv_config(f->unit, PPP_MRU,
                    (go->neg_asyncmap? go->asyncmap: 0x00000000),
                    go->neg_pcompression, go->neg_accompression);
     peer_mru[f->unit] = PPP_MRU;
-
-    link_down(f->unit);
 }
 
 
@@ -1589,7 +1533,7 @@ lcp_printpkt(p, plen, printer, arg)
                    GETSHORT(cishort, p);
                    switch (cishort) {
                    case PPP_PAP:
-                       printer(arg, "upap");
+                       printer(arg, "pap");
                        break;
                    case PPP_CHAP:
                        printer(arg, "chap");
@@ -1640,6 +1584,16 @@ lcp_printpkt(p, plen, printer, arg)
            printer(arg, ">");
        }
        break;
+    case ECHOREQ:
+    case ECHOREP:
+    case DISCREQ:
+       if (len >= 4) {
+           GETLONG(cilong, p);
+           printer(arg, " magic=0x%x", cilong);
+           p += 4;
+           len -= 4;
+       }
+       break;
     }
 
     /* print the rest of the bytes in the packet */
@@ -1660,8 +1614,10 @@ void LcpLinkFailure (f)
     fsm *f;
 {
     if (f->state == OPENED) {
-        syslog (LOG_NOTICE, "Excessive lack of response to LCP echo frames.");
-        lcp_close(f->unit);            /* Reset connection */
+       syslog(LOG_INFO, "No response to %d echo-requests", lcp_echos_pending);
+        syslog(LOG_NOTICE, "Serial link appears to be disconnected.");
+        lcp_close(f->unit, "Peer not responding");
+       phase = PHASE_TERMINATE;
     }
 }
 
@@ -1673,36 +1629,13 @@ static void
 LcpEchoCheck (f)
     fsm *f;
 {
-    long int delta;
-#ifdef __linux__
-    struct ppp_idle    ddinfo;
-/*
- * Read the time since the last packet was received.
- */
-    if (ioctl (fd, PPPIOCGIDLE, &ddinfo) < 0) {
-        syslog (LOG_ERR, "ioctl(PPPIOCGIDLE): %m");
-        die (1);
-    }
-/*
- * Compute the time since the last packet was received. If the timer
- *  has expired then send the echo request and reset the timer to maximum.
- */
-    delta = (long int) lcp_echo_interval - (long int) ddinfo.recv_idle;
-    if (delta < 0L) {
-        LcpSendEchoRequest (f);
-        delta = (int) lcp_echo_interval;
-    }
-
-#else /* Other implementations do not have ability to find delta */
     LcpSendEchoRequest (f);
-    delta = (int) lcp_echo_interval;
-#endif
 
-/*
- * Start the timer for the next interval.
- */
+    /*
    * Start the timer for the next interval.
    */
     assert (lcp_echo_timer_running==0);
-    TIMEOUT (LcpEchoTimeout, (caddr_t) f, (u_int32_t) delta);
+    TIMEOUT (LcpEchoTimeout, (caddr_t) f, lcp_echo_interval);
     lcp_echo_timer_running = 1;
 }
 
@@ -1758,25 +1691,24 @@ LcpSendEchoRequest (f)
     u_int32_t lcp_magic;
     u_char pkt[4], *pktp;
 
-/*
- * Detect the failure of the peer at this point.
- */
+    /*
    * Detect the failure of the peer at this point.
    */
     if (lcp_echo_fails != 0) {
         if (lcp_echos_pending++ >= lcp_echo_fails) {
             LcpLinkFailure(f);
            lcp_echos_pending = 0;
        }
     }
-/*
- * Make and send the echo request frame.
- */
+
+    /*
+     * Make and send the echo request frame.
+     */
     if (f->state == OPENED) {
         lcp_magic = lcp_gotoptions[f->unit].magicnumber;
        pktp = pkt;
        PUTLONG(lcp_magic, pktp);
-      
-        fsm_sdata(f, ECHOREQ,
-                 lcp_echo_number++ & 0xFF, pkt, pktp - pkt);
+        fsm_sdata(f, ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt);
     }
 }
 
@@ -1798,11 +1730,6 @@ lcp_echo_lowerup (unit)
     /* If a timeout interval is specified then start the timer */
     if (lcp_echo_interval != 0)
         LcpEchoCheck (f);
-#ifdef _linux_
-    /* If a idle time limit is given then start it */
-    if (idle_time_limit != 0)
-        RestartIdleTimer (f);
-#endif
 }
 
 /*
@@ -1819,11 +1746,4 @@ lcp_echo_lowerdown (unit)
         UNTIMEOUT (LcpEchoTimeout, (caddr_t) f);
         lcp_echo_timer_running = 0;
     }
-#ifdef _linux_  
-    /* If a idle time limit is running then stop it */
-    if (idle_timer_running != 0) {
-        UNTIMEOUT (IdleTimeCheck, (caddr_t) f);
-        idle_timer_running = 0;
-    }
-#endif
 }