lcp.c

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

C
1,350
字号
   int      rc =  CONFACK; /* Final packet return code */
   int      orc;           /* Individual option return code */
   u_char * p;             /* Pointer to current char to parse */
   u_char * next;          /* scratch "next" pointer */
   u_char * ucp   =  inp;  /* Pointer to current output char */
   int      l = *lenp;     /* Length left */
   u_char   nakcilen;      /* Length of generated Configure-NAK CI (for auth) */
   int      i;             /* index (for copying) */
   lcp_options * go = &mppp->lcp_gotoptions;
   lcp_options * ho = &mppp->lcp_hisoptions;

   /* Process all his options. */
   #if LCP_DEBUG
   Printu("lcp_reqci\r\n");
   #endif
   p = next = inp;
   while (l) 
   {
      orc = CONFACK;          /* Assume success */
      cip = p = next;         /* Remember begining of CI */
      citype = *p++;          /* Parse CI type */
      cilen = *p++;           /* Parse CI length */

      if ((l < 2) ||          /* Not enough data for CI header or */
          (cilen < 2) ||      /* CI length too small or */
          (cilen > l))        /* CI length too big? */
      {
         //ConPrintf(( "lcp_reqci: bad CI length!"));
         orc = CONFREJ;       /* Reject bad CI */
         cilen = (u_char)l;   /* Reject till end of packet */
         l = 0;               /* Don't loop again */
         goto endswitch;
      }
      l -= cilen;             /* Adjust remaining length */
      next += cilen;          /* Step to next CI */

      switch (citype)
      {       /* Check CI type */
      case CI_MRU:
         //ConPrintf(("lcp_reqci: rcvd MRU"));
         if (cilen != CILEN_SHORT)  /* Check CI length */
         {
            orc = CONFREJ;       /* Reject CI */
            break;
         }
         cishort = ppp_getshort(p);   /* Parse MRU */
         //ConPrintf("(%d)", cishort);

         /* He must be able to receive at least our minimum.
          * and don't let him have more than our MTU.
          */
         if(cishort < MINMRU)
         {
            orc = CONFNAK;       /* Nak CI */
            if ( !reject_if_disagree )
               ppp_putshort(p, MINMRU);   /* Give him a hint */
            break;
         }
         ho->neg_mru = 1;     /* Remember he sent MRU */
         ho->mru = cishort;   /* And remember value */
         break;

      case CI_ASYNCMAP:
         //ConPrintf(("lcp_reqci: rcvd ASYNCMAP"));
         if (cilen != CILEN_LONG) 
         {
            orc = CODEREJ;
            break;
         }
         cilong = ppp_getlong(p);
         //ConPrintf("(%lx)", cilong);
	 if(cilong!=ppp_asyncmap_default)
	 {
	     ppp_putlong(p,ppp_asyncmap_default);
	     orc = CONFNAK;
	     break;
	 }		     
         /* Asyncmap must have set at least the bits
          * which are set in allow_asyncmap.
          */
         if ((allow_asyncmap & ~cilong) != 0) 
         {
            #if LCP_DEBUG
            Printu("ASYNMAP:orc = CONFNAK;\r\n");
            #endif
            orc = CONFNAK;
            if ( !reject_if_disagree )
            {
               ppp_putlong(p, (allow_asyncmap | cilong));
            }
            break;
         }
         ho->neg_asyncmap = 1;
         ho->asyncmap = cilong;
         break;

      case CI_AUTHTYPE:
         /*
          * If we aren't willing to send authentication information to 
          * the peer, we should simply configure-reject any authentication
          * protocol.  Else, if the peer is requesting an authentication
          * protocol that we support and are willing to use, we should
          * configure-ack.  Else, we must be willing to do something, so
          * we should pick our preference and configure-nak suggesting
          * that.
          *
          * Preference for authentication protocols: RFC 1334 section 2
          * requires preference of "stronger" authentication protocols
          * (e.g. CHAP) over PAP, but this applies to the peer too so
          * if he requests PAP we should not try to push him toward
          * CHAP.  So we just pick a favorite/best 
          */
        // ConPrintf(("lcp_reqci: rcvd AUTHTYPE"));
         #if LCP_DEBUG
	 Printu("cp_reqci: rcvd AUTHTYP\r\n");
         #endif
         if (cilen < CILEN_SHORT)
         {
            /* too-short authentication-protocol CI: configure-nak */
nak_auth_ci:
            orc = CONFNAK;
            /* if we're just going to reject, don't bother suggesting */
            if (reject_if_disagree)
               break;

            /* figure out how long the CI will be in the configure-nak */
#ifdef CHAP_SUPPORT
            nakcilen = CILEN_SHORT + 1;
#else  /* neg_pap assumed true */
            nakcilen = CILEN_SHORT;
#endif
            /* if it's longer, move the rest of the CIs up to make room */
            if (nakcilen > cilen)
            {
               for (i = l - 1; i >= 0; i--)
                  next[i + (nakcilen - cilen)] = next[i];
               next += (nakcilen - cilen);
            }
            /* start rewriting CI at its length */
            p = cip + 1;
            *p++ = nakcilen;
#ifdef CHAP_SUPPORT
            {
               cishort = PPP_CHAP;
               ppp_putshort(p, cishort);
               p += 2;
#ifdef MSCHAP_SUPPORT
               cichar = CHAP_DIGEST_MSCHAP;
#else
               cichar = CHAP_DIGEST_MD5;
#endif   /* MSCHAP_SUPPORT */
               *p++ = cichar;
            }
#else 
#ifdef PAP_SUPPORT
            {
               cishort = PPP_UPAP;
               ppp_putshort(p, cishort);
               p += 2;
            }
#else
            /* break to reject, we have no auth-protocol support */
            break;
#endif /* PAP_SUPPORT */
#endif /* CHAP_SUPPORT */
            /* remember new length */
            cilen = nakcilen;
            break;
         }

         cishort = ppp_getshort(p);
         p += 2;
         //ConPrintf("(%x)", cishort);

         switch (cishort)
         {
#ifdef   PAP_SUPPORT
         case PPP_UPAP:
            if (cilen != CILEN_SHORT)
            {
               /* short length for PAP: configure-nak */
               goto nak_auth_ci;
            }
            ho->neg_upap = 1;
            break;
#endif /* PAP_SUPPORT */
#ifdef   CHAP_SUPPORT
         case PPP_CHAP:
            if (cilen < (CILEN_SHORT + 1))
            {
               /* short length for CHAP: configure-nak */
               goto nak_auth_ci;
            }
            cichar = *p++;   /* get digest(algorithm) type */

#ifdef MSCHAP_SUPPORT
            if ((cichar != CHAP_DIGEST_MSCHAP)
                && (cichar != CHAP_DIGEST_MD5))
#else
            if (cichar != CHAP_DIGEST_MD5)
#endif   /* MSCHAP_SUPPORT */
            {
               //ConPrintf("Bad MD5 digest type %x, NAKing\n", (int)cichar);
               /* unrecognized algorithm: configure-nak */
               goto nak_auth_ci;
            }

            ho->chap_mdtype = cichar;
            ho->neg_chap = 1;
            break;
#endif /* CHAP_SUPPORT */
         default:
            /* unrecognized protocol: configure-nak */
            goto nak_auth_ci;
         }

         /*
          * If we got here, we're happy with the requested option.
          * Keep it.
          */
         break;

#ifdef LQR_SUPPORT
      case CI_QUALITY:
         //ConPrintf(("lcp_reqci: rcvd QUALITY"));
         if (cilen != CILEN_LQR) 
         {
            orc = CONFREJ;
            break;
         }

         cishort = ppp_getshort(p);
         p += 2;
         cilong = ppp_getlong(p);
         p += 4;
         //ConPrintf("(%x %lx)", cishort, cilong);
         if (cishort != PPP_LQR) 
         {
            orc = CONFREJ;
            break;
         }

         /*
          * Check the reporting period.
          * XXX When should we Nak this, and what with?
          */
         break;
#endif   /* LQR_SUPPORT  - LQR */

      case CI_MAGICNUMBER:
         //ConPrintf("lcp_reqci: rcvd MAGICNUMBER");
         if (!(go->neg_magicnumber) || (cilen != CILEN_LONG))
         {
            orc = CONFREJ;
            break;
         }
         cilong = ppp_getlong(p);   /* leave p at value for now */
         //ConPrintf("(%lx)", cilong);

         /*
          * He must have a different magic number.
          */
         if (go->neg_magicnumber &&
             cilong == go->magicnumber) 
         {
            orc = CONFNAK;
            cilong = ppp_magic(mppp);
            ppp_putlong(p, cilong); /* p still points two value */
            break;
         }
         p += 4;     /* bump past magic number value */
         ho->neg_magicnumber = 1;
         ho->magicnumber = cilong;
         break;

      case CI_PCOMPRESSION:
         //ConPrintf(("lcp_reqci: rcvd PCOMPRESSION"));
         if (cilen != CILEN_VOID) 
         {
            orc = CONFREJ;
            break;
         }
         ho->neg_pcompression = 1;
         break;

      case CI_ACCOMPRESSION:
         //ConPrintf(("lcp_reqci: rcvd ACCOMPRESSION"));
         if (cilen != CILEN_VOID) 
         {
            orc = CONFREJ;
            break;
         }
         ho->neg_accompression = 1;
         break;

#ifdef PPP_MULTILINK
      case CI_ML_MRU:
         /* This option signals that he wants a Multilink capable
          * connection. The actual value of the ML-MRU can be any
          * RFC-legal value.
          */
         //ConPrintf(("lcp_reqci: rcvd MULTILINK_MRU"));
         if((mppp->pppflags & ALLOW_ML) == 0)
         {
            orc = CONFREJ;
            break;
         }
         ho->ml_mru = ppp_getshort(p);
         ho->neg_ml_mru = 1;
         p += 2;
         break;
      case CI_ML_SSN:   /* Short sequence number option OK */
         //ConPrintf(("lcp_reqci: rcvd MULTILINK_SSN"));
         if((mppp->pppflags & ALLOW_ML) == 0)
         {
            orc = CONFREJ;
            break;
         }
         ho->neg_ml_ssn = 1;
         break;
      case CI_ML_ENDP:
         //ConPrintf(("lcp_reqci: rcvd MULTILINK_ENDPT"));
         if((mppp->pppflags & ALLOW_ML) == 0)
         {
            orc = CONFREJ;
            break;
         }
         ho->neg_ml_endp = 1;

         /* fill in MPPP fields from requested Endpoint descriptor. RFC1990
          * disallows NAKing any particular values he wants to use, we can 
          * only reject (or accept) the entire option. We will use these 
          * values to start a new bundle or join an existing one when LCP
          * comes up.
          */
         mppp->ml_conf.endp_class = *p++;
         mppp->ml_conf.endp_length = (u_char)(cilen - 3);
         MEMCPY(mppp->ml_conf.endp_desc, p, cilen - 3);
         break;
#endif
      default:
         //ConPrintf("lcp_reqci: rcvd unknown option %d", citype);
         orc = CONFREJ;
         break;
      }

endswitch:
    //  ConPrintf("(%s)\n", CODENAME(orc));
      if ((orc == CONFACK) &&    /* Good CI and */
          (rc != CONFACK))       /* prior CI wasnt? */
      {
         continue;               /* Don't send this one */
      }

      if (orc == CONFNAK)        /* Nak this CI? */
      {
         if (reject_if_disagree) /* Getting fed up with sending NAKs? */
            orc = CONFREJ;       /* Get tough if so */
         else 
         {
            if (rc == CONFREJ)   /* Rejecting prior CI? */
               continue;         /* Don't send this one */
            if (rc == CONFACK)   /* Ack'd all prior CIs? */
            {
               rc = CONFNAK;     /* Not anymore... */
               ucp = inp;        /* Backup */
            }
         }
      }
      if((orc == CONFREJ) &&     /* Reject this CI */
          (rc != CONFREJ))       /*  but no prior ones? */
      {
         rc = CONFREJ;
         ucp = inp;           /* Backup */
      }
      if (ucp != cip)         /* Need to move CI? */
         MEMCPY(ucp, cip, cilen);   /* Move it */
      ucp += cilen;           /* Update output pointer */
   }

   /*
    * If we wanted to send additional NAKs (for unsent CIs), the
    * code would go here.  This must be done with care since it might
    * require a longer packet than we received.  At present there
    * are no cases where we want to ask the peer to negotiate an option.
    */

   *lenp = ucp - inp;         /* Compute output length */
   //ConPrintf("lcp_reqci: returning CONF%s.\n", CODENAME(rc));

   /* RFC1661 actions (pg 10) don't distinguish between send-conf-nak and
    * send-conf-reject; however we need to. Set the PPP flags bit to
    * indicate to the logic which will form the NAK/REJ reply which code
    * to use.
    */
   if(rc == CONFREJ)
      mppp->pppflags |= SEND_REJECT;
   else
      mppp->pppflags &= ~SEND_REJECT;

   return (rc);               /* Return final code */
}



/* FUNCTION: lcp_finished()
 *
 * lcp_finished - LCP has finished with the lower layer.
 *
 * 
 * PARAM1: M_PPP mppp
 *
 * RETURNS: 
 */

void
lcp_finished(M_PPP mppp)
{
   #if LCP_DEBUG
   Printu("lcp_finished\r\n");
   #endif
   mppp->line.ln_disconnect(&mppp->line);
}


/* FUNCTION: lcp_starting()
 *
 * lcp_starting - LCP needs the lower layer up.
 *
 * PARAM1: M_PPP mppp
 *
 * RETURNS: void
 */

void
lcp_starting(M_PPP mppp)
{
   #if LCP_DEBUG
   Printu("lcp_starting\r\n");
   #endif
   mppp->line.ln_connect(&mppp->line);
}


#endif   /* USE_PPP */
/* end of file lcp.c */



⌨️ 快捷键说明

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