lcp.c

来自「在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LE」· C语言 代码 · 共 1,350 行 · 第 1/3 页

C
1,350
字号
      {
         /* We can only use our single global MLED */
         *ucp++ = CI_ML_ENDP;
         *ucp++ = (u_char)(3 + ml_endplen);    /* length of option field */
         *ucp++ = (u_char)(ml_endpclass);
         /* If class is IP address, and data is not set; then set it now */
         if((ml_endpclass == MLEDCLASS_IP) &&
            (*(ip_addr*)(&ml_endp[0]) == 0) &&
            (mppp->ifp))
         {
            *(ip_addr*)(&ml_endp[0]) = mppp->ifp->n_ipaddr;
         }
         MEMCPY(ucp, ml_endp, ml_endplen);
         ucp += ml_endplen;
      }
   }
#endif  /* PPP_MULTILINK */

#ifdef LQR_SUPPORT
   if(go->neg_lqr)
   {
      *ucp++ = CI_QUALITY;
      *ucp++ = CILEN_LQR;
      ucp = ppp_putshort(ucp, PPP_LQR);
      ucp = ppp_putlong(ucp + 2, go->lqr_period);
   }
#endif   /* LQR_SUPPORT */

   if(go->neg_magicnumber)
   {
      *ucp++ = CI_MAGICNUMBER;
      *ucp++ = CILEN_LONG;
      ucp = ppp_putlong(ucp, go->magicnumber);
   }
   if(go->neg_pcompression)
   {
      *ucp++ = CI_PCOMPRESSION;
      *ucp++ = CILEN_VOID;
   }
   if(go->neg_accompression)
   {
      *ucp++ = CI_ACCOMPRESSION;
      *ucp++ = CILEN_VOID;
   }
   len = ucp - &mppp->lastci[0];

#ifdef NPDEBUG
   if(len > MAX_CILEN)
   {
      //ConPrintf("ci too big for buffer\n");
      dtrap("lcp 1\n");    /* programming error */
      return 0;
   }
#endif   /* NPDEBUG */
   //PrintString('x',&mppp->lastci[0],len);
   return (len);
}


/* FUNCTION: lcp_ackci()
 *
 * lcp_ackci - received Ack of our CIs.
 * This should not modify any state if the Ack is bad.
 *
 * 
 * PARAM1: mppp         - our PPP connection
 * PARAM2: u_char * p   - received CI data
 * PARAM3: int len      - length of ucp
 *
 * RETURNS: 0 if Ack was good or nonzero if Ack was bad.
 */

int
lcp_ackci(M_PPP mppp, u_char * p, int len)
{
   int  ci_ok;

   #if LCP_DEBUG
   Printu("lcp_ackci\r\n");
   #endif
   ci_ok = MEMCMP(p, mppp->lastci, len);
  // ConPrintf("LCP rcvd ACK: %s\n", ci_ok?"BAD":"OK");
   return ci_ok;
}


/* FUNCTION: lcp_nakci()
 *
 * lcp_nakci - Peer has sent a NAK for some of our CIs.
 * This should not modify any state if the Nak is bad
 * or if LCP is in the OPENED state.
 *
 *
 * PARAM1: M_PPP mppp
 * PARAM2: u_char * p
 * PARAM3: int len
 *
 * RETURNS: 0 - Nak was good or 1 if Nak was bad
 */

int
lcp_nakci(M_PPP mppp, u_char * p, int len)
{
   u_char   cilen;
   u_short  cishort;
   u_long   cilong;
   lcp_options no;      /* options we've seen Naks for */
   lcp_options tryfor;  /* options to request next time */
   lcp_options * go = &mppp->lcp_gotoptions;
   lcp_options * wo = &mppp->lcp_wantoptions;
   int   looped_back =  0;

   #if LCP_DEBUG
   Printu("lcp_nakci\r\n");
   #endif
   /* initialize local option lists */
   MEMSET(&no, 0, sizeof(no));         /* null NAK list */
   MEMCPY(&tryfor, go, sizeof(*go));   /* copy latest "got" list */

   //ConPrintf("rcvd NAK; ");
   /* loop through NAKed options */
   while(len > 0)
   {
      if((*p) > CI_LCP_MAX)
      {
         //ConPrintf("Bad LCP option 0x%x\n", *p);
         return 1;
      }
      //ConPrintf("opt:%s ", lcp_opts[*p]);
      cilen = *(p + 1);    /* length of this option field */
      switch (*p)          /* switch based on option */
      {
         case CI_MRU:
            /* if he NAKed an option we didn't send, punt pkt */
            if(go->neg_mru == 0)
               goto rcvd_bad_nak;
            /*
             * We don't care if they want to send us smaller packets than we
             * want.  Therefore, accept any MRU less than what we asked for
             * but then ignore the new value when setting the MRU. 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.
             */
            no.neg_mru = 1;
            cishort = ppp_getshort(p + 2);
            if (cishort <= wo->mru || cishort < ppp_mru)
               tryfor.mru = cishort;
            break;
         case CI_ASYNCMAP:
            /* Add any characters they want to our (receive-side) asyncmap. */
            if(go->neg_asyncmap == 0)
               goto rcvd_bad_nak;
            no.neg_asyncmap = 1;
            cilong = ppp_getlong(p + 2);
            tryfor.asyncmap = go->asyncmap | cilong;
            break;
         case CI_AUTHTYPE:
            /* If they can't cope with our CHAP hash algorithm, we'll have
             * to stop asking for CHAP. We haven't got any other algorithm.
             */
            if(go->neg_chap)
            {
               tryfor.neg_chap = 0;
               tryfor.neg_upap = 1;    /* ask for PAP instead */
            }
            else     /* They NAKed UPAP? */
            {
               if(go->neg_upap == 0)   /* bad pkt */
                  goto rcvd_bad_nak;
               /* Peer shouldn't send Nak for UPAP, protocol compression or
                * address/control compression requests; they should send
                * a Reject instead. If they sent a Nak, treat it as a Reject.
                */
               tryfor.neg_upap = 0;
            }
            break;

#ifdef LQR_SUPPORT
         case CI_QUALITY:
            /*
             * If they can't cope with our link quality protocol, we'll have
             * to stop asking for LQR.  We haven't got any other protocol.
             * Some folks can't hold their LIQR.
             * If they Nak the reporting period, take their value.
             */
            if(go->neg_lqr == 0)
               goto rcvd_bad_nak;
            no.neg_lqr = 1;
            cishort = ppp_getshort(p + 2);
            cilong = ppp_getlong(p + 4);
            if (cishort != PPP_LQR)
               tryfor.neg_lqr = 0;
            else
               tryfor.lqr_period = cilong;
            break;
#endif /* LQR_SUPPORT */

         case CI_PCOMPRESSION:
            if(go->neg_pcompression == 0)
               goto rcvd_bad_nak;
            no.neg_pcompression = 1;
            tryfor.neg_pcompression = 0;
            break;
         case CI_ACCOMPRESSION:
            if(go->neg_accompression == 0)
               goto rcvd_bad_nak;
            no.neg_accompression = 1;
            tryfor.neg_accompression = 0;
            break;
         case CI_MAGICNUMBER:
            /* Check for a looped-back line. */
            if(go->neg_magicnumber == 0)
               goto rcvd_bad_nak;
            no.magicnumber = 1;
            tryfor.magicnumber = ppp_magic(mppp);
            ++tryfor.numloops;
            looped_back = 1;
            break;
#ifdef PPP_MULTILINK
         case CI_ML_MRU:
            if(go->neg_ml_mru == 0)
               goto rcvd_bad_nak;
            if((mppp->pppflags & ALLOW_ML) == 0)
            {
               no.neg_ml_mru = 0;
               break;
            }
            no.neg_ml_mru = 1;
            /* If he suggested short MRU try for it */
            if(go->ml_mru < ppp_mru)
               tryfor.ml_mru = go->ml_mru;
            else
               tryfor.ml_mru = ppp_mru;  /* else repeat our best offer */
            break;
         case CI_ML_SSN:
            if(go->neg_ml_ssn == 0)
               goto rcvd_bad_nak;
            if((mppp->pppflags & ALLOW_ML) == 0)
            {
               no.neg_ml_ssn = 0;
               break;
            }
            no.neg_ml_ssn = 1;
            /* We don;t really care about this, try without it */
            tryfor.neg_ml_ssn = 0;
            break;
         case CI_ML_ENDP:
            goto rcvd_bad_nak;   /* he's not supposed to NAK this */
            break;
#endif   /* PPP_MULTILINK */
         default:
           // ConPrintf("lcp: Bad NAK option 0x%x\n", *p);
            goto rcvd_bad_nak;
      }
      p += cilen;
      len -= cilen;
   }

   /* Nak is good - update "gotoptions" so we can confreq again. */

   if (mppp->states[LCP_STATE] != ST_OPENED) 
   {
      MEMCPY(go, &tryfor, sizeof(tryfor));
      if (looped_back && ((tryfor.numloops % lcp_warnloops) == 0))
      {
        // ConPrintf("The line appears to be looped back; closing:");
         ppp_close(mppp, LCP_STATE);
      }
   }
   else
   {
      //ConPrintf("Got LCP NAK in OPENED state.");
   }
   //ConPrintf("\n");
   return 0;   /* good return */

rcvd_bad_nak:
   //ConPrintf("lcp: rcvd bad NAK (option:0x%x)\n", *p);
   return 1;
}


/* FUNCTION: lcp_rejci()
 *
 * lcp_rejci - Peer has Rejected some of our CIs.
 * This should not modify any state if the Reject is bad
 * or if LCP is in the OPENED state.
 *
 * 
 * PARAM1: M_PPP mppp
 * PARAM2: u_char *p
 * PARAM3: int len
 *
 * RETURNS: One of the CI reject events:
 *     EV_RXJC - unrecoverable rejection, kill session.
 *     EV_RXJP - tolerable rejection, try other option.
 *     EV_NOEVENT - packet was badly formed, ignore it.
 */

int
lcp_rejci(M_PPP mppp, u_char * p, int len)
{
   lcp_options * go = &mppp->lcp_gotoptions;
   u_char   cilen;
   u_short  cishort;
   u_long   cilong;
   lcp_options tryfor;        /* options to request next time */

   
   #if LCP_DEBUG
   Printu("lcp_rejci\r\n");
   #endif
   MEMCPY(&tryfor, go, sizeof(tryfor));

   while(len > 0)
   {
      cilen = *(p + 1);    /* length of this option field */
      //ConPrintf("lcp reject of 0x%x\n", *p);
      switch(*p)
      {
         case CI_MRU:
            if(go->neg_mru == 0)
               goto rcvd_bad_rej;
            cishort = ppp_getshort(p + 2);
            if(cishort != go->mru)  /* did he rej wrong value? */
               goto rcvd_bad_rej;
            tryfor.neg_mru = 0;
            break;
         case CI_ASYNCMAP:
            if(go->neg_asyncmap == 0)
               goto rcvd_bad_rej;
            cilong = ppp_getlong(p + 2);
            if(cilong != go->asyncmap)  /* did he rej wrong value? */
               goto rcvd_bad_rej;
            tryfor.neg_asyncmap = 0;
            break;
         case CI_AUTHTYPE:
            if(go->neg_chap)
            {
               tryfor.neg_chap = 0;
               tryfor.neg_upap = 1;    /* ask for PAP instead */
            }
            else     /* They rejected UPAP? */
            {
               if(go->neg_upap == 0)   /* bad pkt */
                  goto rcvd_bad_rej;
               tryfor.neg_upap = 0;
            }
            break;

#ifdef LQR_SUPPORT
         case CI_QUALITY:
            if(go->neg_lqr == 0)
               goto rcvd_bad_rej;
            cishort = ppp_getshort(p + 2);
            if(cishort != PPP_LQR)  /* did he rej wrong value? */
               goto rcvd_bad_rej;
            tryfor.neg_lqr = 0;
            break;
#endif   /* LQR_SUPPORT */

         case CI_MAGICNUMBER:
            if(go->magicnumber == 0)
               goto rcvd_bad_rej;
            cilong = ppp_getlong(p + 2);
            if(cilong != go->magicnumber) /* check rejected value */
               goto rcvd_bad_rej;
            tryfor.neg_magicnumber = 0;
            break;
         case CI_PCOMPRESSION:
            if(go->neg_pcompression == 0)
               goto rcvd_bad_rej;
            tryfor.neg_pcompression = 0;
            break;
         case CI_ACCOMPRESSION:
            if(go->neg_accompression == 0)
               goto rcvd_bad_rej;
            tryfor.neg_accompression = 0;
            break;
#ifdef PPP_MULTILINK
         case CI_ML_MRU:
            if(go->neg_ml_mru == 0)
               goto rcvd_bad_rej;
            tryfor.neg_ml_mru = 0;  /* forget about multilink */
            break;
         case CI_ML_SSN:
            if(go->neg_ml_ssn == 0)
               goto rcvd_bad_rej;
            tryfor.neg_ml_ssn = 0;
            break;
         case CI_ML_ENDP:
            if(go->neg_ml_endp == 0)
               goto rcvd_bad_rej;
            tryfor.neg_ml_endp = 0;
            break;
#endif
         default:
            //ConPrintf("lcp: REG for bad option 0x%x\n", *p);
            goto rcvd_bad_rej;
      }
      p += cilen;
      len -= cilen;
   }

   /* Now we can update state. */
   if (mppp->states[LCP_STATE] != ST_OPENED)
      MEMCPY(go, &tryfor, sizeof(tryfor));
   return EV_RXJP;

rcvd_bad_rej:
   //ConPrintf("lcp_rejci: bad; len %d opt: 0x%x", len, *p);
   return EV_NOEVENT;
}


/* FUNCTION: lcp_reqci()
 *
 * lcp_reqci - Check the peer's requested CIs and send
 * appropriate response.
 *
 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
 * appropriately.  If reject_if_disagree is non-zero, doesn't return
 * CONFNAK; returns CONFREJ if it can't return CONFACK.
 *
 * This leaves the reply option list for NAK, ACK or REJ in inp with 
 * the reply length set in lenp.
 *
 * 
 * PARAM1: M_PPP mppp
 * PARAM2: u_char * inp
 * PARAM3: int * lenp
 * PARAM4: int reject_if_disagree
 *
 * RETURNS: CONFACK, CONFNAK or CONFREJ
 */

int
lcp_reqci(M_PPP mppp,
   u_char * inp,  /* Requested CIs */
   int * lenp,    /* Length of requested CIs */
   int   reject_if_disagree)
{
   u_char * cip;           /* Pointer to current and next CIs */
   u_char   cilen;         /* length of current CI */
   u_char   citype;        /* type of CI */
#ifdef   CHAP_SUPPORT      /* char only used for MD5 digest type */
   u_char   cichar;        /* Parsed char value */
#endif
   u_short  cishort;       /* Parsed short value */
   u_long   cilong;        /* Parse long value */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?