http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / userapps / opensource / ppp / pppoe / lcp.c
index e954b91..ca39cbd 100755 (executable)
@@ -17,7 +17,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: lcp.c,v 1.57 2001/03/08 05:11:14 paulus Exp $"
+#define RCSID  "$Id: lcp.c,v 1.5 2006/11/24 03:33:52 andylin Exp $"
 
 /*
  * TODO:
 
 static const char rcsid[] = RCSID;
 
+/*wilson add for MS-CHAPv2, 05/26/2005*/
+extern bool refuse_chap;
+/*wilson add end*/
+
 /*
  * When the link comes up we want to be able to wait for a short while,
  * or until seeing some input from the peer, before starting to send
@@ -52,15 +56,23 @@ static void lcp_delayed_up __P((void *));
 /*
  * LCP-related command-line options.
  */
-static int idle_for_echo=120;
-int    lcp_echo_interval = 30;         /* Interval between LCP echo-requests */
-int    lcp_echo_fails = 3;     /* Tolerance to unanswered echo-requests */
+//Charles 09/01/2003, original=5, 5, 3
+static int idle_for_echo=10;
+//int  lcp_echo_interval = 10;         /* Interval between LCP echo-requests */
+int    lcp_echo_interval = 20;
+int    lcp_echo_fails = 6;     /* Tolerance to unanswered echo-requests */
 //int  lcp_echo_interval = 0;  /* Interval between LCP echo-requests */
 //int  lcp_echo_fails = 0;     /* Tolerance to unanswered echo-requests */
 bool   lax_recv = 0;           /* accept control chars in asyncmap */
 bool   noendpoint = 0;         /* don't send/accept endpoint discriminator */
 bool   auth_failed = 0;
 
+#if defined(INCLUDE_MTU_LAN_PPP)
+extern glb_CONFIG_PPP_MTU;
+#endif
+
+extern int ppp_session; //andy add
+
 static int noopt __P((char **));
 
 #ifdef HAVE_MULTILINK
@@ -335,7 +347,21 @@ lcp_init(unit)
     wo->neg_mru = 1;
     wo->mru = DEFMRU;
     wo->neg_asyncmap = 1;
+    /*wilson modify for MS-CHAPv2, 05/26/2005*/
+    //wo->chap_mdtype = CHAP_DIGEST_MD5;
+    wo->use_digest = 1;
+#ifdef CHAPMS
+    if(wo->use_chapms_v2)
+       wo->chap_mdtype = CHAP_MICROSOFT_V2;
+    else if(wo->use_chapms)
+       wo->chap_mdtype = CHAP_MICROSOFT;
+    else
+#endif
+    if(wo->use_digest)
     wo->chap_mdtype = CHAP_DIGEST_MD5;
+    else
+       refuse_chap = 1;
+    /*wilson modify end*/
     wo->neg_magicnumber = 1;
     wo->neg_pcompression = 1;
     wo->neg_accompression = 1;
@@ -345,7 +371,23 @@ lcp_init(unit)
     ao->mru = MAXMRU;
     ao->neg_asyncmap = 1;
     ao->neg_chap = 1;
+    /*wilson modify for MS-CHAPv2, 05/26/2005*/
+    //ao->chap_mdtype = CHAP_DIGEST_MD5;
+    ao->use_digest = 1;
+#ifdef CHAPMS
+    ao->use_chapms_v2 = ao->use_chapms = 1;
+    if(ao->use_chapms_v2)
+       ao->chap_mdtype = CHAP_MICROSOFT_V2;
+    else if(ao->use_chapms)
+       ao->chap_mdtype = CHAP_MICROSOFT;
+    else
+#else
+    if(ao->use_digest)
     ao->chap_mdtype = CHAP_DIGEST_MD5;
+    else
+       refuse_chap = 1;
+#endif
+    /*wilson modify end*/
     ao->neg_upap = 1;
     ao->neg_magicnumber = 1;
     ao->neg_pcompression = 1;
@@ -354,6 +396,7 @@ lcp_init(unit)
     ao->neg_cbcp = 1;
 #endif
     ao->neg_endpoint = 1;
+
 }
 
 
@@ -455,8 +498,7 @@ lcp_lowerup(unit)
      * if we are going to ask for A/C and protocol compression.
      */
     ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0);
-    ppp_recv_config(unit, PPP_MRU, (lax_recv? 0: 0xffffffff),
-                   wo->neg_pcompression, wo->neg_accompression);
+    ppp_recv_config(unit, PPP_MRU, (lax_recv? 0: 0xffffffff), wo->neg_pcompression, wo->neg_accompression);
     peer_mru[unit] = PPP_MRU;
 
     if (listen_time != 0) {
@@ -633,8 +675,7 @@ lcp_sprotrej(unit, p, len)
     p += 2;
     len -= 2;
 
-    fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id,
-             p, len);
+    fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len);
 }
 
 
@@ -651,6 +692,12 @@ lcp_resetci(f)
 
     wo->magicnumber = magic();
     wo->numloops = 0;
+
+    if (ppp_session == PPPOA)//Andy modify
+       wo->mru = 1500;
+    else
+       wo->mru = 1492;
+
     *go = *wo;
     if (!multilink) {
        go->neg_mrru = 0;
@@ -684,7 +731,21 @@ lcp_cilen(f)
      * NB: we only ask for one of CHAP and UPAP, even if we will
      * accept either.
      */
-    return (LENCISHORT(go->neg_mru && go->mru != DEFMRU) +
+    /*wilson add for MS-CHAPv2, 05/26/2005*/
+#ifdef CHAPMS
+    if(go->use_chapms_v2)
+       go->chap_mdtype = CHAP_MICROSOFT_V2;
+    else if(go->use_chapms)
+       go->chap_mdtype = CHAP_MICROSOFT;
+    else
+#endif
+    if(go->use_digest)
+       go->chap_mdtype = CHAP_DIGEST_MD5;
+    else
+       go->neg_chap = 0;
+    /*wilson add end*/
+
+    return (LENCISHORT(go->neg_mru /*&& go->mru != DEFMRU //andy modify it*/) +
            LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
            LENCICHAP(go->neg_chap) +
            LENCISHORT(!go->neg_chap && go->neg_upap) +
@@ -710,7 +771,6 @@ lcp_addci(f, ucp, lenp)
 {
     lcp_options *go = &lcp_gotoptions[f->unit];
     u_char *start_ucp = ucp;
-
 #define ADDCIVOID(opt, neg) \
     if (neg) { \
        PUTCHAR(opt, ucp); \
@@ -757,8 +817,10 @@ lcp_addci(f, ucp, lenp)
        for (i = 0; i < len; ++i) \
            PUTCHAR(val[i], ucp); \
     }
+    //go->mru = lcp_allowoptions[0].mru;
 
-    ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
+    //ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
+    ADDCISHORT(CI_MRU, go->neg_mru, go->mru);
     ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
              go->asyncmap);
     ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
@@ -775,6 +837,7 @@ lcp_addci(f, ucp, lenp)
 
     if (ucp - start_ucp != *lenp) {
        /* this should never happen, because peer_mtu should be 1500 */
+               printf("Bug in lcp_addci: wrong length\n");
        error("Bug in lcp_addci: wrong length");
     }
 }
@@ -905,7 +968,8 @@ lcp_ackci(f, p, len)
        } \
     }
 
-    ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
+       //ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
+       ACKCISHORT(CI_MRU, go->neg_mru, go->mru);
     ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
              go->asyncmap);
     ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
@@ -949,6 +1013,7 @@ lcp_nakci(f, p, len)
 {
     lcp_options *go = &lcp_gotoptions[f->unit];
     lcp_options *wo = &lcp_wantoptions[f->unit];
+    lcp_options *ho = &lcp_hisoptions[f->unit];//andy add
     u_char citype, cichar, *next;
     u_short cishort;
     u_int32_t cilong;
@@ -956,10 +1021,8 @@ lcp_nakci(f, p, len)
     lcp_options try;           /* options to request next time */
     int looped_back = 0;
     int cilen;
-
     BZERO(&no, sizeof(no));
     try = *go;
-
     /*
      * Any Nak'd CIs must be in exactly the same order that we sent.
      * Check packet length and CI length at each step.
@@ -1051,11 +1114,40 @@ lcp_nakci(f, p, len)
      * If they send us a bigger MRU than what we asked, accept it, up to
      * the limit of the default MRU we'd get if we didn't negotiate.
      */
-    if (go->neg_mru && go->mru != DEFMRU) {
+    if (go->neg_mru /*&& go->mru != DEFMRU */) {
+               //lcp_allowoptions[0].mru = wo->mru;//andy add
+               //go->mru = wo->mru;//andy add
+#if 0          
+               if (ho->mru != 0){//andy add            
+                       lcp_allowoptions[0].mru = ho->mru;
+               } else {
+                       //lcp_allowoptions[0].mru = DEFMRU;
+                       if (wo->neg_mru == 1 && wo->mru != 0)
+                               lcp_allowoptions[0].mru = wo->mru;
+                       else
+                               lcp_allowoptions[0].mru = DEFMRU;       
+               }
+#endif                 
        NAKCISHORT(CI_MRU, neg_mru,
                   if (cishort <= wo->mru || cishort <= DEFMRU)
                       try.mru = cishort;
                   );
+                  
+               /* Start andy add */
+               if (cishort > 0 && cishort <= DEFMRU){
+                       lcp_allowoptions[0].mru =  cishort;
+               } else {
+                       if (ho->mru != 0){              
+                               lcp_allowoptions[0].mru = ho->mru;
+                       } else {
+                               if (wo->neg_mru == 1 && wo->mru != 0)
+                                       lcp_allowoptions[0].mru = wo->mru;
+                               else
+                                       lcp_allowoptions[0].mru = DEFMRU;       
+                       }
+               }
+               /* End andy add */
+                  
     }
 
     /*
@@ -1100,14 +1192,45 @@ lcp_nakci(f, p, len)
                 * if we support it, otherwise we'll have to stop
                 * asking for CHAP.
                 */
-               if (cichar != go->chap_mdtype) {
-#ifdef CHAPMS
-                   if (cichar == CHAP_MICROSOFT)
-                       go->chap_mdtype = CHAP_MICROSOFT;
+              /*wilson modify for MS-CHAPv2, 05/26/2005*/
+               if (go->chap_mdtype == CHAP_MICROSOFT_V2)
+               {
+                   try.use_chapms_v2 = 0;
+                   if(try.use_chapms)
+                       try.chap_mdtype = CHAP_MICROSOFT;
+                   else if(try.use_digest)
+                       try.chap_mdtype = CHAP_DIGEST_MD5;
+                   else
+                       try.neg_chap = 0;
+               }
+               else if(go->chap_mdtype == CHAP_MICROSOFT)
+               {
+                   try.use_chapms = 0;
+                   if(try.use_digest)
+                       try.chap_mdtype = CHAP_DIGEST_MD5;
                    else
-#endif /* CHAPMS */
                        try.neg_chap = 0;
                }
+               else if(go->chap_mdtype == CHAP_DIGEST_MD5)
+               {
+                   try.use_digest = 0;
+                   try.neg_chap = 0;
+               }
+               else
+                   try.neg_chap = 0;
+               if ((cichar != CHAP_MICROSOFT_V2) &&
+                   (cichar != CHAP_MICROSOFT) &&
+                   (cichar != CHAP_DIGEST_MD5))
+                       try.neg_chap = 0;
+//             if (cichar != go->chap_mdtype) {
+//#ifdef CHAPMS
+//                 if (cichar == CHAP_MICROSOFT)
+//                     go->chap_mdtype = CHAP_MICROSOFT;
+//                 else
+//#endif /* CHAPMS */
+//                     try.neg_chap = 0;
+//             }
+              /*wilson modify end*/
            } else {
                /*
                 * Stop asking for PAP if we were asking for it.
@@ -1211,7 +1334,7 @@ lcp_nakci(f, p, len)
 
        switch (citype) {
        case CI_MRU:
-           if ((go->neg_mru && go->mru != DEFMRU)
+           if ((go->neg_mru /* && go->mru != DEFMRU */)
                || no.neg_mru || cilen != CILEN_SHORT)
                goto bad;
            GETSHORT(cishort, p);
@@ -1280,11 +1403,11 @@ lcp_nakci(f, p, len)
            try.numloops = 0;
        *go = try;
     }
-
     return 1;
 
 bad:
     LCPDEBUG(("lcp_nakci: received bad Nak!"));
+    printf("lcp_nakci: received bad Nak!\n");
     return 0;
 }
 
@@ -1351,8 +1474,24 @@ lcp_rejci(f, p, len)
        /* Check rejected value. */ \
        if (cishort != val || cichar != digest) \
            goto bad; \
+       /*wilson modify for MS-CHAPv2, 05/26/2005*/ \
+       switch(digest) \
+       { \
+           case CHAP_MICROSOFT_V2: \
+               try.use_chapms_v2 = 0; \
+               break; \
+           case CHAP_MICROSOFT: \
+               try.use_chapms = 0; \
+               break; \
+           case CHAP_DIGEST_MD5: \
+               try.use_digest = 0; \
+       } \
+       if(!try.use_chapms_v2 && !try.use_chapms && !try.use_digest) \
+       { \
        try.neg = 0; \
        try.neg_upap = 0; \
+       } \
+       /*wilson modify end*/ \
     }
 #define REJCILONG(opt, neg, val) \
     if (go->neg && \
@@ -1552,8 +1691,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
            break;
 
        case CI_AUTHTYPE:
-           if (cilen < CILEN_SHORT ||
-               !(ao->neg_upap || ao->neg_chap)) {
+           if (cilen < CILEN_SHORT || !(ao->neg_upap || ao->neg_chap)) {
                /*
                 * Reject the option if we're not willing to authenticate.
                 */
@@ -1572,7 +1710,10 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
             * Whether we end up doing CHAP or UPAP depends then on
             * the ordering of the CIs in the peer's Configure-Request.
             */
-
+               //Andy add for auto PVC
+               if (autoscan == 1 && (cishort == PPP_PAP || cishort == PPP_CHAP)){
+                       create_msg(BCM_PPPOE_SERVICE_AVAILABLE);                
+               }
            if (cishort == PPP_PAP) {
                if (ho->neg_chap ||     /* we've already accepted CHAP */
                    cilen != CILEN_SHORT) {
@@ -1587,16 +1728,17 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
                    PUTSHORT(PPP_CHAP, nakp);
                    PUTCHAR(ao->chap_mdtype, nakp);
                    // brcm
-                   //if (!auth_failed) {
-                       printf("PPP: Authentication failed.---\n");
+                   if (!auth_failed) {
+                       printf("PPP: Authentication failed.\n");
                        create_msg(BCM_PPPOE_AUTH_FAILED); 
-                       syslog(LOG_ERR,"Authentication method failed.\n");
-                       need_holdoff = 0;
+                           //syslog(LOG_ERR,"Authentication method failed.\n");
                        auth_failed = 1;
-                       //lcp_close(0, "Auth failed");
-                       status = EXIT_AUTH_TOPEER_FAILED;
-                   //}
-                   persist=1;              
+                       lcp_close(0, "Auth failed");
+                       need_holdoff = 0;
+                       status = EXIT_PEER_AUTH_FAILED;
+                       exit(0);
+                   }
+                   persist=0;              
                    /* XXX if we can do CHAP_MICROSOFT as well, we should
                       probably put in another option saying so */
                    break;
@@ -1617,25 +1759,29 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
                    PUTCHAR(CILEN_SHORT, nakp);
                    PUTSHORT(PPP_PAP, nakp);
                    // brcm
-                   //if (!auth_failed) {
-                       printf("PPP: Authenication failed.---\n");
+                   if (!auth_failed) {
+                       printf("PPP: Authentication failed.\n");
                        create_msg(BCM_PPPOE_AUTH_FAILED); 
-                       syslog(LOG_ERR,"Authentication method failed.\n");
-                       need_holdoff = 0;
+                           //syslog(LOG_ERR,"Authentication method failed.\n");
                        auth_failed = 1;
-                       //lcp_close(0, "Auth failed");
-                       status = EXIT_AUTH_TOPEER_FAILED;
-                   //}
-                   persist=1;              
+                       lcp_close(0, "Auth failed");
+                       need_holdoff = 0;
+                       exit(0);
+                   }
+                   persist=0;              
                    break;
                }
                GETCHAR(cichar, p);     /* get digest type*/
                if (cichar != CHAP_DIGEST_MD5
 #ifdef CHAPMS
                    && cichar != CHAP_MICROSOFT
+                           && cichar != CHAP_MICROSOFT_V2     /*wilson add for MS-CHAPv2, 05/26/2005*/
 #endif
                    ) {
-                   orc = CONFNAK;
+                         /*wilson modify for MS-CHAPv2, 05/26/2005*/
+                           //orc = CONFNAK;
+                           orc = CONFREJ; /* !!! CONFNAK !!! */
+                         /*wilson modify end*/
                    PUTCHAR(CI_AUTHTYPE, nakp);
                    PUTCHAR(CILEN_CHAP, nakp);
                    PUTSHORT(PPP_CHAP, nakp);
@@ -1665,8 +1811,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
            break;
 
        case CI_QUALITY:
-           if (!ao->neg_lqr ||
-               cilen != CILEN_LQR) {
+           if (!ao->neg_lqr || cilen != CILEN_LQR) {
                orc = CONFREJ;
                break;
            }
@@ -1689,8 +1834,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
            break;
 
        case CI_MAGICNUMBER:
-           if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
-               cilen != CILEN_LONG) {
+           if (!(ao->neg_magicnumber || go->neg_magicnumber) || cilen != CILEN_LONG) {
                orc = CONFREJ;
                break;
            }
@@ -1699,8 +1843,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
            /*
             * He must have a different magic number.
             */
-           if (go->neg_magicnumber &&
-               cilong == go->magicnumber) {
+           if (go->neg_magicnumber && cilong == go->magicnumber) {
                cilong = magic();       /* Don't put magic() inside macro! */
                orc = CONFNAK;
                PUTCHAR(CI_MAGICNUMBER, nakp);
@@ -1714,8 +1857,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
 
 
        case CI_PCOMPRESSION:
-           if (!ao->neg_pcompression ||
-               cilen != CILEN_VOID) {
+           if (!ao->neg_pcompression || cilen != CILEN_VOID) {
                orc = CONFREJ;
                break;
            }
@@ -1723,8 +1865,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
            break;
 
        case CI_ACCOMPRESSION:
-           if (!ao->neg_accompression ||
-               cilen != CILEN_VOID) {
+           if (!ao->neg_accompression || cilen != CILEN_VOID) {
                orc = CONFREJ;
                break;
            }
@@ -1732,8 +1873,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
            break;
 
        case CI_MRRU:
-           if (!ao->neg_mrru || !multilink ||
-               cilen != CILEN_SHORT) {
+           if (!ao->neg_mrru || !multilink || cilen != CILEN_SHORT) {
                orc = CONFREJ;
                break;
            }
@@ -1745,8 +1885,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
            break;
 
        case CI_SSNHF:
-           if (!ao->neg_ssnhf || !multilink ||
-               cilen != CILEN_VOID) {
+           if (!ao->neg_ssnhf || !multilink || cilen != CILEN_VOID) {
                orc = CONFREJ;
                break;
            }
@@ -1754,9 +1893,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
            break;
 
        case CI_EPDISC:
-           if (!ao->neg_endpoint ||
-               cilen < CILEN_CHAR ||
-               cilen > CILEN_CHAR + MAX_ENDP_LEN) {
+           if (!ao->neg_endpoint || cilen < CILEN_CHAR || cilen > CILEN_CHAR + MAX_ENDP_LEN) {
                orc = CONFREJ;
                break;
            }
@@ -1838,7 +1975,6 @@ lcp_up(f)
     lcp_options *go = &lcp_gotoptions[f->unit];
     lcp_options *ao = &lcp_allowoptions[f->unit];
     int mtu;
-
     if (!go->neg_magicnumber)
        go->magicnumber = 0;
     if (!ho->neg_magicnumber)
@@ -1853,21 +1989,31 @@ lcp_up(f)
      * the interface MTU is set to the lower of that and the
      * MTU we want to use.
      */
+#if 0    
     mtu = ho->neg_mru? ho->mru: PPP_MRU;
+#else
+       #if defined(CONFIG_LANG_MMM) || defined(ODM_LANG_LLL)//Andy add (2005/06/20)
+       mtu = glb_CONFIG_PPP_MTU;
+       #else 
+       mtu = ho->neg_mru? ho->mru: glb_CONFIG_PPP_MTU;
+       #endif
+#endif    
 #ifdef HAVE_MULTILINK
     if (!(multilink && go->neg_mrru && ho->neg_mrru))
 #endif /* HAVE_MULTILINK */
        netif_set_mtu(f->unit, MIN(mtu, ao->mru));
-    ppp_send_config(f->unit, MIN(mtu, ao->mru),
+    ppp_send_config(f->unit, mtu,
                    (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
                    ho->neg_pcompression, ho->neg_accompression);
     ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU),
                    (lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff),
                    go->neg_pcompression, go->neg_accompression);
-
+#if 0 //andy commit    
     if (ho->neg_mru)
        peer_mru[f->unit] = ho->mru;
-
+#else//andy modify
+       peer_mru[f->unit] = mtu;
+#endif
     lcp_echo_lowerup(f->unit);  /* Enable echo messages */
 
     link_established(f->unit);
@@ -1875,7 +2021,7 @@ lcp_up(f)
     // brcm
     if (!auth_failed)
         create_msg(BCM_PPPOE_SERVICE_AVAILABLE);
-    syslog(LOG_CRIT,"PPP LCP UP.\n");
+    syslog(LOG_NOTICE,"PPP LCP Up\n");
 }