⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pppfsm.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifdef PAP_SUPPORT
      case PPP_UPAP:
         #if PPPFSM_DEBUG
         Printu("PPP_UPAP\r\n");
	 #endif
         upap_input(mppp, inp, plen);
         goto drop;
#endif
#ifdef CHAP_SUPPORT
      case PPP_CHAP:
         #if PPPFSM_DEBUG
         Printu("PPP_CHAP\r\n");
	 #endif
         ChapInput(mppp, inp, plen);
         goto drop;
#endif
#ifdef PPP_MULTILINK
      case PPP_ML:
         pppml_rcv(mppp, pkt);
         return;
#endif   /* PPP_MULTILINK */
      default:
       //  ConPrintf("ppp_inpkt: (link %p): unsupported prot %x\n", mppp, proto);
         /* send protocol reject packet */
         ppp_sendctl(mppp, LCP_STATE, PROTREJ, (u_char*)pkt->nb_prot,
            pkt->nb_plen, mppp->in_ids[LCP_STATE]);
         LOCK_NET_RESOURCE(FREEQ_RESID);
         pk_free(pkt);
         UNLOCK_NET_RESOURCE(FREEQ_RESID);
         return;
   }

   /* Fall to here if it's one of the FSM control protocols.
    * get the protocol header and do length error checking
    */

   code = *inp;      /* FSM op-code */
   mppp->in_ids[pcode] = *(inp + 1);      /* save Id for possible reply */
   hlen = (int)ppp_getshort(inp + 2);

   /* verify packet is not truncated & plen is OK */
   if((hlen > plen) || (plen < 4))
   {
     // ConPrintf("(link %p) truncated packet, lengths: hdr:%d, actual:%d\n", mppp, hlen, plen);
      goto drop;
   }

   /* set pointer & length to CI list after header */
   inp += 4;
   plen -= 4;

   //ConPrintf("ppp_inpkt (link %p); prot: %s, code %s, state %s, len %d\n", 
      //mppp, prots[pcode], codes[code], fsmstate[mppp->states[pcode]], plen );

   /* We shouldn't be getting packets in states INITIAL and STARTING */
   if(mppp->states[pcode] < ST_CLOSED)
   {
 //     ConPrintf("(link %p) got pkt in state %s\n", mppp,
    //     fsmstate[mppp->states[pcode]]);
      goto drop;
   }

   /* Call the receive routine and map the FSM packet type code
    * to an event type for the state table.
    */
   pfuncs = &prot_func_tabs[pcode];
   err = -1;
   hlen -= 4;     /* deduct header size before passing to routines */
   reject = (mppp->naks_received[pcode] >= ppp_maxnaks) ? TRUE : FALSE;
   event = EV_NOEVENT;     /* stifle compiler warnings */
   mppp->rxcode = code;    /* save last code received */
   switch (code)
   {
      case CONFREQ:        /* Configuration Request */
         if(pfuncs->reqci)
            err = pfuncs->reqci(mppp, inp, &hlen, reject);
         if(err == CONFACK)
            event = EV_RCROK;
         else
            event = EV_RCRBAD;   /* NAK, REJ, or bad pkt */
         break;
      case CONFACK:        /* Configuration Ack */
         if(pfuncs->ackci)
            err = pfuncs->ackci(mppp, inp, hlen);
         if(err == 0)
            event = EV_RCA;
         else
            event = EV_NOEVENT;
         break;
      case CONFNAK:        /* Configuration Nak */
         if(pfuncs->nakci)
            err = pfuncs->nakci(mppp, inp, hlen);
         if(err == 0)
            event = EV_RCN;
         else
            event = EV_NOEVENT;
         break;
      case CONFREJ:        /* Configuration Reject */
         if(pfuncs->rejci)
            event = pfuncs->rejci(mppp, inp, hlen);
         break;
      case TERMREQ:        /* Termination Request */
         event = EV_RTR;
         break;
      case TERMACK:        /* Termination Ack */
         event = EV_RTA;
         break;
      case CODEREJ:        /* Code Reject */
         event = EV_RXJP;
         break;
      case PROTREJ:        /* Protocol Reject */
         if(pcode == PPP_IPCP)
         {
            /* This is pretty serious, log it */
           // ConPrintf("(link %p) Prot-Reject for IPCP, closing\n", mppp);
            /* signal FSM as though lowest layer went down */
            ppp_lowerdown(mppp, LCP_STATE);
            event = EV_RXJC;        /* set event for TLF later */
         }
         else
         {
           // ConPrintf("(link %p) Prot-Reject for %x\n", mppp, proto);
            event = EV_RXJP;        /* almost a no-op */
         }
         break;
      case PECHOREQ:       /* Echo Request */
         /* To prepare ECHOREP we have to insert our magic number */
         ppp_putlong(inp, mppp->lcp_gotoptions.magicnumber);
         /* No break; fall into RXR event code */
      case DISCREQ:        /* Discard Request */
         event = EV_RXR;
         break;
      case PECHOREP:       /* Echo Reply */
         if(mppp_echo_callback)
            mppp_echo_callback(mppp, inp, hlen);
         LOCK_NET_RESOURCE(FREEQ_RESID);
         pk_free(pkt);
         UNLOCK_NET_RESOURCE(FREEQ_RESID);
         return;
#ifdef PPP_IDENTIFY
      case IDENTITY:       /* LCP Indentity request */
         if(proto == PPP_LCP)    /* verify this is LCP code */
         {
            int   idlen;   /* length of received ID info */

            /* Technically this is an LCP pkt, however it's more 
             * efficeint to just handle it in-line here.
             * Save Identity string in mppp and null-terminate for
             * printf()ing. Make sure we don;t overrun mppp->identity
             * buffer. At this point inp points to a 4 byte "magic number"
             * field, which we skip.
             */
            idlen = min((hlen - 4), (PPP_MAX_IDENTITY - 1));
            MEMCPY(mppp->identity, (inp + 4), idlen);
            mppp->identity[idlen] = 0;  /* null-term */

            /* RFC-1570 suggests we should both log this and print to user */
           // ConPrintf("rcvd IDENTITY: %s\n", mppp->identity);
            dprintf("rcvd IDENTITY: %s\n", mppp->identity);
            LOCK_NET_RESOURCE(FREEQ_RESID);
            pk_free(pkt);
            UNLOCK_NET_RESOURCE(FREEQ_RESID);
            return;
         }
         /* else fall into "unknown code" logic */
#endif /* PPP_IDENTIFY */
      default:
         //ConPrintf("(link %p) unknown code: %x", mppp, code);
         if(pfuncs->extcode)
            pfuncs->extcode(mppp, code, CODEREJ, inp, hlen);
         LOCK_NET_RESOURCE(FREEQ_RESID);
         pk_free(pkt);
         UNLOCK_NET_RESOURCE(FREEQ_RESID);
         return;
   }

   /* do the FSM actions indicated in the table */
   ppp_fsm(mppp, pcode, event, inp, hlen);

drop:
   LOCK_NET_RESOURCE(FREEQ_RESID);
   pk_free(pkt);
   UNLOCK_NET_RESOURCE(FREEQ_RESID);
   return;
}

/* FUNCTION: ppp_fsm()
 *
 * Perform the FSM transition and actions for the passed mppp to handle
 * the passed code and event.
 *
 * PARAM1: M_PPP mppp      - session 
 * PARAM2: unsigned pcode  - protocol code (LCP, IPCP, etc.)
 * PARAM3: int event       - one of the EV_ event codes
 * PARAM4: u_char * inp    - packet data for received packet events
 * PARAM5: int inlen       - length of inp
 *
 * RETURNS: void
 */

void
ppp_fsm(M_PPP mppp, unsigned pcode, int event, u_char * inp, int inlen)
{
   unshort  cmd;        /* series of 4-bit actions code from FSM table */
   u_char   newstate;   /* state we end up in after FSM change */
   u_char   oldstate;   /* state before FSM change */
   int      i;          /* index */
   int      state;      /* state of this mppp */
   int      action;     /* next 4-bit action code from cmd */
   prot_funcs * pfuncs; /* pointer to protocol function table */
   u_char   replytype;  /* code for reply */
   u_char * outp;       /* pointer to reply send data */
   int      outlen;     /* length of reply to send, if any */
   u_char   reply_id;   /* PPP header ID to put in output pkt, if any */

   if(event == EV_NOEVENT)
      return;
#ifdef NPDEBUG
   if((event > NUM_PPPEVENTS) || (pcode > IPCP_STATE))
   {
      dtrap("pppfsm 1\n");	/* PARAMETER OUT OF RANGE */
      return;
   }
#endif   /* NPDEBUG */

   pfuncs = &prot_func_tabs[pcode];
   state = mppp->states[pcode];

   /* Take action and fix state machine based on state table */
   cmd = fsm_table[(state * NUM_PPPEVENTS) + event];

   if(cmd == 0xFFFF)
   {
      //ConPrintf("fsm_input (link %p): bad state: %d, event:%d.", 
         //mppp, state, event);
      ppp_cleartimer(mppp);
      return;
   }
   newstate = (u_char)(cmd & 0x000F);  /* extract new state */
   oldstate = mppp->states[pcode];     /* remember current state */
   cmd &= 0xFFF0;                      /* mask out state nibble */

  // ConPrintf("ppp_fsm (link %p): %s state: %s -> %s\n",
     // mppp, prots[pcode], fsmstate[oldstate], fsmstate[newstate]);

   /* if this is the beginning of a new session we need to reset the
    * lines options to defaults. New sessions are begun by UP in the LCP
    * layer or OPEN in the IPCP layer
    */
   if((oldstate == ST_INITIAL) &&
      (((event == EV_UP) && (pcode == LCP_STATE)) || 
       ((event == EV_OPEN) && (pcode == IPCP_STATE))))
   {
      ppp_fsm_init(mppp);
   }

   /* If this line just came up without a prior open call then
    * we are the PPP server:
    */
   if((event == EV_UP) && (oldstate == ST_INITIAL))
      mppp->pppflags |= PPP_SERVER;

#ifdef PPP_MULTILINK
   /* if this is a multilink bundle member and it is leaving the 
    * OPENED state then we need to clean up the ML flags.
    */
   if((oldstate == ST_OPENED) && (newstate != ST_OPENED))
       mppp->pppflags &= ~(ML_IPCP|ML_LCP);
#endif

   /* For down or close events clear any running retry timers */
   if((event == EV_DOWN) || (event == EV_CLOSE))
      ppp_cleartimer(mppp);

   /* RFC 1661 seems to imply we should set the state after these 
    * actions are performed, but it seems more robust here. 
    */
   mppp->states[pcode] = newstate;

   /* If we are exiting a timed state to an untimed one
    * we need to clear the timer. 
    */
   if((newstate <= ST_STOPPED) || (newstate >= ST_OPENED))
   {
      /* Old state had a timer? */
      if((oldstate > ST_STOPPED) && (oldstate < ST_OPENED))
         ppp_cleartimer(mppp);
   }

   /* rotate through the three action nibbles, performing the
    * indicated action if it's non-zero
    */
   for(i = 0; i < 3; i++)
   {
      if(cmd == 0)         /* no (more) actions? */
         break;
      replytype = 0xFF;    /* signal for no reply */
      reply_id = mppp->in_ids[pcode];  /* default to reply, may be changed */
      outp = inp;          /* set default reply CI data */
      outlen = inlen;      /* and default send CI length */
      action = cmd >> 12;  /* get next 4-bit action code */
      switch(action)
      {
      case AC_TLU:      /* This-Layer-Up */
         if(pfuncs->up)
            pfuncs->up(mppp);
         break;
      case AC_TLD:      /* This-Layer-Down */
         if(pfuncs->down)
            pfuncs->down(mppp);
         break;
      case AC_TLS:      /* This-Layer-Started */
         if(pfuncs->starting)
            pfuncs->starting(mppp);
         break;
      case AC_TLF:      /* This-Layer-Finished */
         if(pfuncs->finished)
            pfuncs->finished(mppp);
         break;
      case AC_IRC:      /* Initialize-Restart-Count (and timer) */
         mppp->retrys = PPP_FSMTRYS;
         if(mppp->tmo_tick)
            mppp->tmo_tick = cticks + (ppp_retry_secs * (u_long)TPS);
         break;
      case AC_ZRC:      /* Zero-Restart-Count */
         ppp_cleartimer(mppp);
         break;
      case AC_SCR:      /* Send-Configure-Request */
         replytype = CONFREQ;
         reply_id = mppp->out_ids[pcode]++;
         if((state != ST_REQSENT) && 
            (state != ST_ACKRCVD) && 
            (state != ST_ACKSENT ))
         {
            /* Not currently negotiating - reset options */
            if(pfuncs->resetci)
               (pfuncs->resetci)(mppp);
            mppp->nakloops = 0;
         }
         if(pfuncs->addci)
         {
            outlen = pfuncs->addci(mppp);  /* build the confreq in mppp->lastci */
            outp = mppp->lastci;           /* set send pointer */
         }
         break;
      case AC_SCA:      /* Send-Configure-Ack */
         replytype = CONFACK;
         break;
      case AC_SCN:      /* Send-Configure-Nak/Rej */
         /* inp should already have NAK packet, and reject bit should be set */
         if(mppp->pppflags & SEND_REJECT)
         {
            mppp->pppflags &= ~SEND_REJECT;  /* clear flag */
            replytype = CONFREJ;             /* send reject, not NAK */
         }
         else
            replytype = CONFNAK;
         break;
      case AC_STR:      /* Send-Terminate-Request */
         replytype = TERMREQ;
         reply_id = mppp->out_ids[pcode]++;
         outlen = 0;    /* no data, TERMREQ is all header */
         break;
      case AC_STA:      /* Send-Terminate-Ack */
         replytype = TERMACK;
         break;
      case AC_SCJ:      /* Send-Code-Reject */
         dtrap("pppfsm 2\n");
         replytype = CODEREJ;
         break;
      case AC_SER:      /* Send-Echo-Reply (or similar) */
         switch(mppp->rxcode)
         {
         case PECHOREQ:
            replytype = PECHOREP;
            break;
         default:    /* ECHOREP, DISCARD are noop */
            break;
         }
      case 0:           /* noop, just loop back for next action */
         break;
      default:
         dtrap("pppfsm 3\n");
         break;
      }
      cmd <<= 4;     /* shift in next nibble */

      /* See if we need to send a reply type packet */
      if(replytype != 0xFF)
      {
        // ConPrintf("ppp_fsm (link %p) sending %s, len:%d\n", 
        //    mppp, codes[replytype], outlen);
         ppp_sendctl(mppp, pcode, replytype, outp, outlen, reply_id);
      }
   }

   /* If we're entering one of the timed states from an untimed state
    * then start a retry timer. The retry count itself was set 
    * in the IRC and ZRC actions above. 
    */
   if((newstate > ST_STOPPED) && (newstate < ST_OPENED))
   {
      /* old state didn't have a timer? */
      if((oldstate <= ST_STOPPED) || (oldstate >= ST_OPENED))
         ppp_settimer(mppp, ppp_fsm_tmo, ppp_retry_secs, (long)pcode);
   }

   /* If LCP has just gone from CLOSED state to INITIAL it probably
    * means the line failed to connect - our modem code signals this 
    * with a ppp_lowerdown() call. Do a close now on IPCP so it
    * doesn't linger in STARTING state. It's a bit off the spec., but 
    * it makes things work better.
    */
   if((newstate == ST_INITIAL) && 
      (pcode == LCP_STATE))
   {
      //ConPrintf("LCP (%p) failed, closing IPCP\n", mppp);
      ppp_close(mppp, IPCP_STATE);
   }

   return;
}

/* FUNCTION: ppp_fsm_tmo()
 *
 * Handle a PPP FSM timer expiration.
 *
 * PARAM1: M_PPP mppp
 * PARAM2: long parm
 *
 * RETURNS: void
 */

void
ppp_fsm_tmo(M_PPP mppp, long parm)
{
   if(mppp->retrys-- > 1)     /* do we have more retrys? */
   {
      ppp_fsm(mppp, (int)parm, EV_TOP, NULL, 0);      /* another try */
      mppp->tmo_tick = cticks + (ppp_retry_secs * (u_long)TPS);  /* reset timer */
      mppp->tmr_sets++;       /* count this as a set */
   }
   else     /* timed out, clean up */
      ppp_fsm(mppp, (int)parm, EV_TOX, NULL, 0);
}


/* FUNCTION: ppp_fsm_init()
 * 
 * Initialize an mppp structure for a new connect
 *
 * PARAM1: M_PPP mppp
 *
 * RETURNS: void
 */

void
ppp_fsm_init(M_PPP mppp)
{
   lcp_options * lcp_ho = &mppp->lcp_hisoptions;

   //ConPrintf("ppp_fsm_init (link %p)\n", mppp);

   /* Reset peer's options structure. */
   MEMSET(lcp_ho, 0, sizeof(*lcp_ho));

   /* reset our options */
   lcp_resetci(mppp);
   ipcp_resetci(mppp);

   /* Per RFC1662, Default initial asyncmaps to escape all 32 control 
    * chars. These are usually renegotiated and modified by LCP negotiation.
    * Frame oriented links like PPPOE should simply ignore then.
    */
   mppp->his_asyncmap = 0xFFFFFFFF;
   mppp->my_asyncmap = 0xFFFFFFFF;

⌨️ 快捷键说明

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