Ejemplo n.º 1
0
static void PPPFSM_timeout
   (
      void          *fsm_ptr,
            /* [IN/OUT] - State Machine */
      PCB_PTR        packet,
            /* [IN] - expired packet */
      bool        hard
            /* [IN] - TRUE if this is a hard timeout (TO- event) */
   )
{ /* Body */
   PPPFSM_CFG_PTR    fsm = fsm_ptr;

   PPP_mutex_lock(&fsm->MUTEX);
   switch (fsm->STATE) {
   case PPP_STATE_CLOSING:
   case PPP_STATE_STOPPING:
      if (hard) {
         /* We've waited for an ack long enough */
         fsm->STATE -= 2;  /* Stopping/Closing -> Stopped/Closed */
      } /* Endif */
      break;

   case PPP_STATE_REQ_SENT:
   case PPP_STATE_ACK_RCVD:
   case PPP_STATE_ACK_SENT:
      if (hard) {
         fsm->STATE = PPP_STATE_STOPPED;
      } else if (fsm->STATE == PPP_STATE_ACK_RCVD) {
         fsm->STATE = PPP_STATE_REQ_SENT;
      } /* Endif */
      break;
   } /* Endswitch */
   PPP_mutex_unlock(&fsm->MUTEX);

} /* Endbody */
Ejemplo n.º 2
0
static boolean CCP_up
   (
      PPPFSM_CFG_PTR     fsm
            /* [IN] - State Machine */
   )
{ /* Body */
   PPP_CFG_PTR ppp_ptr = fsm->HANDLE;
   CCP_CFG_PTR ccp_ptr = fsm->PRIVATE;
   CP_CALL_PTR cprecv = ccp_ptr->RECV_OPT.CP;
   CP_CALL_PTR cpsend = ccp_ptr->SEND_OPT.CP;

      /* Initialize compression methods */
   if (cprecv) {
      cprecv->CP_init(&ccp_ptr->RECV_DATA, &ccp_ptr->RECV_OPT);
   } /* Endif */
   if (cpsend) {
      cpsend->CP_init(&ccp_ptr->SEND_DATA, &ccp_ptr->SEND_OPT);
   } /* Endif */

   PPP_mutex_lock(&ppp_ptr->MUTEX);
   ppp_ptr->RECV_OPTIONS->CP = cprecv;
   ppp_ptr->SEND_OPTIONS->CP = cpsend;
   PPP_mutex_unlock(&ppp_ptr->MUTEX);

   return TRUE;

} /* Endbody */
Ejemplo n.º 3
0
void PPPFSM_lowerup
   (
      PPPFSM_CFG_PTR    fsm
         /* [IN/OUT] - State Machine */
   )
{ /* Body */

#if RTCSCFG_ENABLE_IP4

   PPP_mutex_lock(&fsm->MUTEX);

   switch(fsm->STATE) {
   case PPP_STATE_INITIAL:
      fsm->STATE = PPP_STATE_CLOSED;
      break;

   case PPP_STATE_STARTING:
      if (fsm->OPTIONS & PPP_OPT_SILENT) {
         fsm->STATE = PPP_STATE_STOPPED;
      } else {
         PPPFSM_sendconfreq(fsm, NULL);
         fsm->STATE = PPP_STATE_REQ_SENT;
      }/* Endif */
      break;
   }  /* Endswitch */

   PPP_mutex_unlock(&fsm->MUTEX);

#endif /* RTCSCFG_ENABLE_IP4 */
   
} /* Endbody */
Ejemplo n.º 4
0
uint32_t PPPFSM_destroy
   (
      PPPFSM_CFG_PTR    fsm
            /* [IN/OUT] - State Machine */
   )
{ /* Body */

#if RTCSCFG_ENABLE_IP4

   uint32_t error = PPP_OK;

   PPP_mutex_lock(&fsm->MUTEX);
   if (fsm->STATE > PPP_STATE_CLOSED) {
      error = RTCSERR_PPP_FSM_ACTIVE;
   } else {
      fsm->STATE = PPP_STATE_INITIAL;
   } /* Endif */
   PPP_mutex_unlock(&fsm->MUTEX);
   if (!error) {
      PPP_mutex_destroy(&fsm->MUTEX);
   } /* Endif */
   return error;

#else   

    return RTCSERR_IP_IS_DISABLED;

#endif /* RTCSCFG_ENABLE_IP4  */   

} /* Endbody */
Ejemplo n.º 5
0
void PPPFSM_open
   (
      PPPFSM_CFG_PTR    fsm,
            /* [IN/OUT] - State Machine */
      uint32_t           options
            /* [IN] - Startup options */
   )
{ /* Body */

#if RTCSCFG_ENABLE_IP4

   PPP_mutex_lock(&fsm->MUTEX);
   fsm->OPTIONS = options;

   switch (fsm->STATE) {
   case PPP_STATE_INITIAL:
      fsm->STATE = PPP_STATE_STARTING;
      break;

   case PPP_STATE_CLOSED:
      if (options & PPP_OPT_SILENT) {
         fsm->STATE = PPP_STATE_STOPPED;
      } else {
         /* Send an initial Configure-Request */
         PPPFSM_sendconfreq(fsm, NULL);
         fsm->STATE = PPP_STATE_REQ_SENT;
      } /* Endif */
      break;

   case PPP_STATE_CLOSING:
      fsm->STATE = PPP_STATE_STOPPING;
      /* fall through */
   case PPP_STATE_STOPPING:
   case PPP_STATE_STOPPED:
      if (options & PPP_OPT_RESTART) {
         PPPFSM_sendconfreq(fsm, NULL);
         fsm->STATE = PPP_STATE_REQ_SENT;
      } /* Endif */
      break;

   case PPP_STATE_OPENED:
      if (options & PPP_OPT_RESTART) {
         if (fsm->CALL->linkdown) {
            fsm->CALL->linkdown(fsm);
         } /* Endif */
         PPPFSM_sendconfreq(fsm, NULL);
         fsm->STATE = PPP_STATE_REQ_SENT;
      } /* Endif */
      break;
   } /* Endswitch */

   PPP_mutex_unlock(&fsm->MUTEX);

#endif /* RTCSCFG_ENABLE_IP4 */

} /* Endbody */
Ejemplo n.º 6
0
void _iopcb_hdlc_rcv_unblock
   (
   pointer param
   /* [IN] The semaphore to unblock when the message arrives */
   )
{  /* Body */
   LWSEM_STRUCT _PTR_ sem = (LWSEM_STRUCT _PTR_)param;
   PPP_mutex_unlock(sem);

}  /* Endbody */
Ejemplo n.º 7
0
uint_32 PPP_register
   (
      _ppp_handle         handle,
            /* [IN] - the PPP state structure */
      uint_16             protocol,
            /* [IN] - protocol */
      void (_CODE_PTR_    callback)(PCB_PTR, pointer),
            /* [IN] - callback function */
      pointer             parameter
            /* [IN] - first parameter for callback function */
   )
{ /* Body */
   PPP_CFG_PTR    ppp_ptr = handle;
   PROT_CALL_PTR  prot_ptr;

   /* Do some error checking */
   if (ppp_ptr->VALID != PPP_VALID) {
      return RTCSERR_PPP_INVALID_HANDLE;
   } else if (!(protocol&1) || (protocol&0x100)) {
      return RTCSERR_PPP_INVALID_PROTOCOL;
   } /* Endif */

   /* Allocate a callback structure */
   prot_ptr = _mem_alloc_system_zero(sizeof(PROT_CALL));
   if (prot_ptr == NULL) {
      return RTCSERR_PPP_ALLOC_CALL_FAILED;
   } /* Endif */
   protocol &= 0xFFFF;
   prot_ptr->PROTOCOL = protocol;
   prot_ptr->CALLBACK = callback;
   prot_ptr->PARAM    = parameter;

   PPP_mutex_lock(&ppp_ptr->MUTEX);

   if (PPP_findprot(ppp_ptr, protocol)) {
      ppp_ptr->PROT_CALLS->CALLBACK = callback;
      ppp_ptr->PROT_CALLS->PARAM    = parameter;
   } else {
      prot_ptr->NEXT      = ppp_ptr->PROT_CALLS;
      ppp_ptr->PROT_CALLS = prot_ptr;
      prot_ptr = NULL;
   } /* Endif */

   PPP_mutex_unlock(&ppp_ptr->MUTEX);

   if (prot_ptr) {
      _mem_free(prot_ptr);
   } /* Endif */

   return PPP_OK;

} /* Endbody */
Ejemplo n.º 8
0
uint_32 PPP_unregister
   (
      _ppp_handle         handle,
            /* [IN] - the PPP state structure */
      uint_16             protocol
            /* [IN] - protocol */
   )
{ /* Body */

#if RTCSCFG_ENABLE_IP4

   PPP_CFG_PTR    ppp_ptr = handle;
   PROT_CALL_PTR  prot_ptr;
   uint_32        error;

   /* Do some error checking */
   if (ppp_ptr->VALID != PPP_VALID) {
      return RTCSERR_PPP_INVALID_HANDLE;
   } else if (!(protocol&1) || (protocol&0x100)) {
      return RTCSERR_PPP_INVALID_PROTOCOL;
   } else if (!(~protocol & 0xC000)) {
      /* Don't allow unregistering LCP */
      return RTCSERR_PPP_INVALID_PROTOCOL;
   } /* Endif */

   /* Remove structure from list */
   protocol &= 0xFFFF;
   prot_ptr = NULL;
   error = RTCSERR_PPP_PROT_NOT_FOUND;
   PPP_mutex_lock(&ppp_ptr->MUTEX);

   if (PPP_findprot(ppp_ptr, protocol)) {
      prot_ptr = ppp_ptr->PROT_CALLS;
      ppp_ptr->PROT_CALLS = prot_ptr->NEXT;
      error = PPP_OK;
   } /* Endif */

   PPP_mutex_unlock(&ppp_ptr->MUTEX);

   if (prot_ptr) {
      _mem_free(prot_ptr);
   } /* Endif */

   return error;

#else

    return RTCSERR_IP_IS_DISABLED;    

#endif /* RTCSCFG_ENABLE_IP4 */  

} /* Endbody */
Ejemplo n.º 9
0
static void PAP_up
   (
      _ppp_handle    handle
            /* [IN] - the PPP state structure */
   )
{ /* Body */
   PPP_CFG_PTR ppp_ptr = handle;

   PPP_mutex_lock(&ppp_ptr->MUTEX);
   ppp_ptr->LINK_AUTH = TRUE;
   PPP_mutex_unlock(&ppp_ptr->MUTEX);

   PPP_up(handle);

} /* Endbody */
Ejemplo n.º 10
0
static void CCP_down
   (
      PPPFSM_CFG_PTR    fsm
            /* [IN] - State Machine */
   )
{ /* Body */
   PPP_CFG_PTR ppp_ptr = fsm->HANDLE;

      /* Restore default compression methods */
   PPP_mutex_lock(&ppp_ptr->MUTEX);
   ppp_ptr->RECV_OPTIONS->CP = PPP_DEFAULT_OPTIONS.CP;
   ppp_ptr->SEND_OPTIONS->CP = PPP_DEFAULT_OPTIONS.CP;
   PPP_mutex_unlock(&ppp_ptr->MUTEX);

} /* Endbody */
Ejemplo n.º 11
0
void PPPFSM_lowerdown
   (
      PPPFSM_CFG_PTR    fsm
         /* [IN/OUT] - State Machine */
   )
{ /* Body */

#if RTCSCFG_ENABLE_IP4

   PPP_CFG_PTR    ppp_ptr = fsm->HANDLE;

   PPP_mutex_lock(&fsm->MUTEX);

   switch(fsm->STATE)  {
   case PPP_STATE_CLOSED:
      fsm->STATE = PPP_STATE_INITIAL;
      break;

   case PPP_STATE_STOPPED:
      fsm->STATE = PPP_STATE_STARTING;
      break;

   case PPP_STATE_CLOSING:
      fsm->STATE = PPP_STATE_INITIAL;
      PPP_send_stop(ppp_ptr, fsm->CALL->PROTOCOL);
      break;

   case PPP_STATE_STOPPING:
   case PPP_STATE_REQ_SENT:
   case PPP_STATE_ACK_RCVD:
   case PPP_STATE_ACK_SENT:
      fsm->STATE = PPP_STATE_STARTING;
      PPP_send_stop(ppp_ptr, fsm->CALL->PROTOCOL);
      break;

   case PPP_STATE_OPENED:
      if (fsm->CALL->linkdown) {
         fsm->CALL->linkdown(fsm);
      } /* Endif */
      fsm->STATE = PPP_STATE_STARTING;
      break;
   } /* Endswitch */

   PPP_mutex_unlock(&fsm->MUTEX);

#endif /* RTCSCFG_ENABLE_IP4 */
   
} /* Endbody */
Ejemplo n.º 12
0
void PPPFSM_close
   (
      PPPFSM_CFG_PTR    fsm
            /* [IN/OUT] - State Machine */
   )
{ /* Body */

#if RTCSCFG_ENABLE_IP4

   PPP_mutex_lock(&fsm->MUTEX);
   switch (fsm->STATE) {
   case PPP_STATE_STARTING:
      fsm->STATE = PPP_STATE_INITIAL;
      break;
   case PPP_STATE_STOPPED:
      fsm->STATE = PPP_STATE_CLOSED;
      break;
   case PPP_STATE_STOPPING:
      fsm->STATE = PPP_STATE_CLOSING;
      break;

   case PPP_STATE_OPENED:
      if (fsm->CALL->linkdown) {
         fsm->CALL->linkdown(fsm);
      } /* Endif */
      /* fall through */
   case PPP_STATE_REQ_SENT:
   case PPP_STATE_ACK_RCVD:
   case PPP_STATE_ACK_SENT:
      PPPFSM_sendtermreq(fsm, NULL);
      fsm->STATE = PPP_STATE_CLOSING;
      break;
   } /* Endswitch */
   PPP_mutex_unlock(&fsm->MUTEX);

#endif /* RTCSCFG_ENABLE_IP4 */

} /* Endbody */
Ejemplo n.º 13
0
void PPP_rx_task
   (
      pointer     handle,
            /* [IN] - the PPP state structure */
      pointer     creator
            /* [IN] - the task create information */
   )
{ /* Body */

   PPP_CFG_PTR          ppp_ptr = handle;
   PCB_PTR              pcb;
   boolean              linkstate, linkauth;
   PPP_OPT              opt;
   uint_16              protocol, len;
   void (_CODE_PTR_     callback)(PCB_PTR, pointer);
   pointer              param;


#if RTCS_PRINT_PPP_PACKETS
/****/
    uint_32 i;
    uchar_ptr a;
/****/
#endif


   ppp_ptr->RX_TASKID = RTCS_task_getid();
   RTCS_task_resume_creator(creator, PPP_OK);







      /* Wait for incoming packets */
    for (;;) 
    {
        /* new fix */ 
        //check if app shutdown (STOP_RX == TRUE)                
        if(ppp_ptr->STOP_RX)
        {
            break;
        }     
        /***********/

      /**********************************************************
      **
      **    Wait for a frame
      **
      */

        /* Read a frame */
        /*Lets use flag for send pointer to ppp_ptr->STOP_RX */
        pcb = _iopcb_read(ppp_ptr->DEVICE, (uint_32)&(ppp_ptr->STOP_RX));  
        /* new fix */   
        if(NULL == pcb)  
 	    {  
 	        _time_delay(1);  
 		    continue;  
        }  
        /***********/


 #if RTCS_PRINT_PPP_PACKETS
       /* TBR */ 
       /* This part  print input packet */
       a =  pcb->FRAG[0].FRAGMENT;
       i=0;
       printf("receive 7E FF 03 ");
       while(i< (pcb->FRAG[0].LENGTH)+2)
       {
            
            if(*a < 0x10)
            {
                printf("0");
            }
            printf("%X ",*a);
            i++;
            a++;
       } 
       printf("7E\n");
       /*******/
#endif
      len = pcb->FRAG[0].LENGTH;
      if (len < 2) {
         PCB_free(pcb);
         ppp_ptr->ST_RX_RUNT++;
         continue;
      } /* Endif */
      protocol = ntohs(pcb->FRAG[0].FRAGMENT);

      /* Read the negotiated Receive options */
      PPP_mutex_lock(&ppp_ptr->MUTEX);
      linkstate = ppp_ptr->LINK_STATE;
      linkauth  = ppp_ptr->LINK_AUTH;
      opt = *ppp_ptr->RECV_OPTIONS;
      PPP_mutex_unlock(&ppp_ptr->MUTEX);

      /* Discard all non-LCP packets until the link is opened */
      if (protocol != PPP_PROT_LCP) {
         if (!linkstate) {
            PCB_free(pcb);
            ppp_ptr->ST_RX_DISCARDED++;
            continue;
         } /* Endif */
         /* and all non-AP packets until the link is authenticated */
         if (protocol != opt.AP) {
            if (!linkauth) {
               PCB_free(pcb);
               ppp_ptr->ST_RX_DISCARDED++;
               continue;
            } /* Endif */
         } /* Endif */
      } /* Endif */

      /* Decompress the packet if compression was negotiated */
      if ((protocol == PPP_PROT_CP) && opt.CP) {
         pcb = opt.CP->CP_decomp(&ppp_ptr->CCP_STATE.RECV_DATA, pcb, ppp_ptr, &opt);
         protocol = ntohs(pcb->FRAG[0].FRAGMENT);
      } /* Endif */

      /**********************************************************
      **
      **    Forward the packet to higher-level protocol
      **
      */

      /* Find out where to send the packet */
      ppp_ptr->ST_RX_RECEIVED++;


      /*
      ** We could put the known protocols in the PROT_CALLS
      ** list, but we don't because we always want them to
      ** work, even if someone tries to PPP_unregister() them.
      */
      switch (protocol) {

         /* Got an LCP packet */
      case PPP_PROT_LCP:
         LCP_input(pcb, &ppp_ptr->LCP_FSM);
         break;

         /* Got a CCP packet */
      case PPP_PROT_CCP:
         CCP_input(pcb, &ppp_ptr->CCP_FSM);
         break;

         /* Got a PAP packet */
      case PPP_PROT_PAP:
         PAP_input(pcb, ppp_ptr);
         break;

         /* Got a CHAP packet */
      case PPP_PROT_CHAP:
         CHAP_input(pcb, ppp_ptr);
         break;

      default:
         callback = NULL;
         PPP_mutex_lock(&ppp_ptr->MUTEX);
         if (PPP_findprot(ppp_ptr, protocol)) {
            callback = ppp_ptr->PROT_CALLS->CALLBACK;
            param    = ppp_ptr->PROT_CALLS->PARAM;
         } /* Endif */
         PPP_mutex_unlock(&ppp_ptr->MUTEX);

         if (callback) {
            callback(pcb, param);
         } else {
            /* No callback found -- Send Protocol-Reject */
            LCP_sendprotrej(pcb, &ppp_ptr->LCP_FSM);
         } /* Endif */
         break;
      } /* Endswitch */

   } /* Endfor */
   /* We can start task again. (STOP_RX == FALSE) */
   ppp_ptr->STOP_RX = FALSE; 

} /* Endbody */
Ejemplo n.º 14
0
uint32_t PPP_send
   (
      _ppp_handle    handle,
            /* [IN] - the PPP state structure */
      uint16_t        protocol,
            /* [IN] - protocol for the packet */
      PCB_PTR        pcb
            /* [IN] - the packet to send */
   )
{ /* Body */

#if RTCSCFG_ENABLE_IP4

   PPP_CFG_PTR       ppp_ptr = handle;
   PCB_FRAGMENT_PTR  frag_ptr;
   uint32_t           size, mru;
   uint32_t           error;

   /* Do some error checking */
   if (ppp_ptr->VALID != PPP_VALID) {
      PCB_free(pcb);
      return RTCSERR_PPP_INVALID_HANDLE;
   } else if (!(protocol&1) || (protocol&0x100)) {
      PCB_free(pcb);
      return RTCSERR_PPP_INVALID_PROTOCOL;
   } /* Endif */

   error = PPP_OK;
   PPP_mutex_lock(&ppp_ptr->MUTEX);
   if (!ppp_ptr->LINK_STATE) {
      error = RTCSERR_PPP_LINK_NOT_OPEN;
   } else {
      /* SPR P122-0371-01 */
      /* PCB includes 2-byte protocol field, but negotiated MRU doesn't */
      mru = ppp_ptr->SEND_OPTIONS->MRU + 2;
      /* End SPR P122-0371-01 */
   } /* Endif */
   PPP_mutex_unlock(&ppp_ptr->MUTEX);
   if (error) {
      PCB_free(pcb);
      return error;
   } /* Endif */

   /*
   ** Make sure the first fragment is long enough for the PPP protocol
   ** field.  This isn't strictly necessary, but it's impractical
   ** to split a 2 byte field over multiple fragments.
   */
   if (pcb->FRAG[0].LENGTH < 2) {
      PCB_free(pcb);
      return RTCSERR_PPP_PACKET_TOO_SHORT;
   } /* Endif */

   /*
   ** Make sure that no fragment exceeds a maximum packet length.
   ** We check every fragment because we want to prevent something
   ** like FRAG[0].LENGTH = 2000, FRAG[1].LENGTH = -1000.  This
   ** situation would not be detected if we only check the total
   ** length.
   */
   size = 0;
   for (frag_ptr = pcb->FRAG; frag_ptr->LENGTH; frag_ptr++) {
      if (frag_ptr->LENGTH > mru) {
         PCB_free(pcb);
         return RTCSERR_PPP_PACKET_TOO_LONG;
      } /* Endif */
      size += frag_ptr->LENGTH;
   } /* Endfor */

   /*
   ** Make sure that the total sum of the fragments doesn't exceed
   ** a maximum packet length.
   */
   if (size > mru) {
      PCB_free(pcb);
      return RTCSERR_PPP_PACKET_TOO_LONG;
   } /* Endif */

   /*
   ** Everything checks out -- send the packet to the Tx task.
   */
   mqx_htons(pcb->FRAG[0].FRAGMENT, protocol);
   return PPP_send_one(ppp_ptr, protocol, pcb);

#else

    return RTCSERR_IP_IS_DISABLED;    

#endif /* RTCSCFG_ENABLE_IP4 */     

} /* Endbody */
Ejemplo n.º 15
0
void PPP_tx_task
   (
      void       *handle,
            /* [IN] - the PPP state structure */
      void       *creator
            /* [IN] - the creation information */
   )
{ /* Body */

#if RTCSCFG_ENABLE_IP4

   PPP_CFG_PTR       ppp_ptr = handle;
   uint32_t           ctrl;
   bool           state;
   PPP_OPT           opt;
   PCB_PTR           pcb;
   uint32_t           pcbopt;
   PPP_MESSAGE_PTR   message, xmithead, * xmitnode;
   uint32_t           timebefore, timeafter;
   bool           wait;
   int32_t            timeout;
   uint16_t           protocol;
   _queue_id         queue;
   void             *param;

   /* Obtain a message queue so that PPP_send() can reach us */
   queue = RTCS_msgq_open(0, 0);
   if (queue == 0) {
      RTCS_task_exit(creator, RTCSERR_PPP_OPEN_QUEUE_FAILED);
   } /* Endif */

   RTCS_task_resume_creator(creator, PPP_OK);

   ppp_ptr->MSG_QUEUE = queue;

   xmithead = NULL;
   timebefore = RTCS_time_get();

#define PPPTX_DISCARD(msg) \
            (msg)->PCB->FREE = (msg)->ORIG_FREE;   \
            PCB_free((msg)->PCB);                  \
            RTCS_msg_free(msg)

   for(;;)
   {

      /**********************************************************
      **
      **    Wait for a packet to send
      **
      */

      wait = TRUE;
      timeout = 0;

      /* Check if a packet is waiting for retransmission */
      if (xmithead) {

         /* Measure elapsed time */
         timeafter = RTCS_time_get();
         timeout = RTCS_timer_get_interval(timebefore, timeafter); 
         timebefore = timeafter;
         xmithead->DELTA -= timeout;

         /* If its timer has expired, send it */
         timeout = xmithead->DELTA;
         if (timeout <= 0) {
            message = NULL;
            wait = FALSE;
         } /* Endif */
      } /* Endif */

      /*
      ** There are three cases at this point:
      **    1) Retransmission queue is empty
      **          (wait == TRUE,  timeout == 0, message == ?)
      **    2) Retransmission queue is nonempty, positive timeout
      **          (wait == TRUE,  timeout > 0,  message == ?)
      **    3) Retransmission queue is nonempty, nonpositive timeout,
      **       i.e., head of retransmission queue timed out
      **          (wait == FALSE, timeout == 0, message == NULL)
      */

      /* If there are no expired messages, block */
      if (wait) {
         message = RTCS_msgq_receive(queue, timeout, ppp_ptr->MSG_POOL);
      } /* Endif */

      /*
      ** There are two cases at this point:
      **    1) We got a message from _msgq_receive
      **          (message != NULL)
      **    2) Head of retransmission queue timed out
      **          (message == NULL)
      */

      /* We got a packet to send */
      if (message) {

         /* Control packets restart or stop retransmission */
         ctrl = message->COMMAND;

         if (ctrl == PPPCMD_SHUTDOWN) {
            param = message->PARAM;
            /* Free the message we just got */
            RTCS_msg_free(message);
            for (xmitnode = &xmithead;;){
               if (*xmitnode == NULL) {
                  break;
               } else {
                 /* unlink */
                 message = *xmitnode;
                 *xmitnode = message->NEXT;
                 /* Free the message from the list */
                 PPPTX_DISCARD(message);
               } /* Endif */
            } /* Endfor */
            RTCS_msgq_close(queue);
            /* Unblock PPP_shutdown() */
            RTCS_sem_post(param);
            /* Kill self */
            return;
         } /* Endif */
         
         if (ctrl != PPPCMD_SEND) {
            protocol = message->PROTOCOL;
            RTCS_msg_free(message);

            /*
            ** Search the retransmission queue for a packet
            ** matching the protocol field of the control message
            */
            for (xmitnode = &xmithead;;
                 xmitnode = &(*xmitnode)->NEXT) {
               if (*xmitnode == NULL) {
                  break;
               } else if ((*xmitnode)->PROTOCOL == protocol) {
                  message = *xmitnode;
                  switch (ctrl) {
                  case PPPCMD_RESTART:
                     message->TIMEOUT = _PPP_MIN_XMIT_TIMEOUT;
                     message->RETRY = _PPP_MAX_CONF_RETRIES;
                     break;
                  case PPPCMD_STOP:
                     if (message->NEXT) {
                        message->NEXT->DELTA += message->DELTA;
                     } /* Endif */
                     *xmitnode = message->NEXT;
                     PPPTX_DISCARD(message);
                     break;
                  } /* Endswitch */
                  break;
               } /* Endif */
            } /* Endfor */

            continue;
         } /* Endif */

         /* Save the PCB's FREE field */
         message->ORIG_FREE = message->PCB->FREE;
         if (message->TIMEOUT) {
            message->PCB->FREE = PPP_tx_pcbfree;
         } /* Endif */

      /* Receive timed out -- get the head of the retransmission queue */
      } else {
         message = xmithead;
         xmithead = message->NEXT;
         if (xmithead) {
            xmithead->DELTA += message->DELTA;
         } /* Endif */

         /* Generate a TO event */
         if (message->CALL) {
            message->CALL(message->PARAM, message->PCB, message->RETRY == 1);
         } /* Endif */

         /* RETRY == 0 means retry forever */
         if (message->RETRY) {

            /* When the retry count reaches zero, discard the packet */
            if (!--message->RETRY) {
               PPPTX_DISCARD(message);
               continue;
            } /* Endif */
         } /* Endif */

         /* Use exponential backoff when retransmitting */
         message->TIMEOUT <<= 1;
         if (message->TIMEOUT > _PPP_MAX_XMIT_TIMEOUT) {
            message->TIMEOUT = _PPP_MAX_XMIT_TIMEOUT;
         } /* Endif */
      } /* Endif */

      /**********************************************************
      **
      **    We have a packet -- validate it
      **
      */

      /* Take a snapshot of the current state and send options */
      PPP_mutex_lock(&ppp_ptr->MUTEX);
      state = ppp_ptr->LINK_STATE;
      opt = *ppp_ptr->SEND_OPTIONS;
      PPP_mutex_unlock(&ppp_ptr->MUTEX);

      /* Send the data packet (unless the link is not open) */
      if (!state && message->PROTOCOL != PPP_PROT_LCP) {
         PPPTX_DISCARD(message);
         ppp_ptr->ST_TX_DISCARDED++;
         continue;
      } /* Endif */

      /**********************************************************
      **
      **    We have a valid packet -- send it
      **
      */

      /* LCP control packets are always sent with default options */
      if (message->PROTOCOL == PPP_PROT_LCP
       && message->PCB->FRAG[0].FRAGMENT[2] >= 1
       && message->PCB->FRAG[0].FRAGMENT[2] <= 7) {
         pcbopt = 1;
      } else {
         pcbopt = 0;
      } /* Endif */

      pcb = message->PCB;

      /* Only data packets are compressed */
      /* Start CR 2296 */
      //if (((message->PROTOCOL & 0xC000) == 0) && opt.CP) {
      /* End CR 2296 */
      //   pcb = opt.CP->CP_comp(&ppp_ptr->CCP_STATE.SEND_DATA, pcb, ppp_ptr, &opt);
      //   mqx_htons(pcb->FRAG[0].FRAGMENT, PPP_PROT_CP);
      //} /* Endif */

      _iopcb_write(ppp_ptr->DEVICE, pcb, pcbopt);

      /**********************************************************
      **
      **    Packet is sent -- update retransmission queue
      **
      */

      /* Free the buffer unless it may need to be retransmitted */
      if (message->TIMEOUT) {

         /* Measure elapsed time */
         timeafter = RTCS_time_get();
         timeout = RTCS_timer_get_interval(timebefore, timeafter); 
         timebefore = timeafter;
         if (xmithead) {
            xmithead->DELTA -= timeout;
         } /* Endif */

         /* Insert packet into proper place in retransmission queue */
         for (message->DELTA = message->TIMEOUT,    xmitnode = &xmithead;;
              message->DELTA -= (*xmitnode)->DELTA, xmitnode = &(*xmitnode)->NEXT) {
            if (*xmitnode == NULL) {
               /* Add packet at tail of queue */
               message->NEXT = NULL;
               *xmitnode = message;
               break;
            } else if ((*xmitnode)->DELTA > message->TIMEOUT) {
               /* Insert packet in middle (possibly head) of queue */
               (*xmitnode)->DELTA -= message->DELTA;
               message->NEXT = *xmitnode;
               *xmitnode = message;
               break;
            } /* Endif */
         } /* Endfor */

      } else {
         /* PCB has already been freed by _iopcb_write() */
         RTCS_msg_free(message);
      } /* Endif */

   } /* Endfor */
#endif /* RTCSCFG_ENABLE_IP4 */
   
} /* Endbody */
Ejemplo n.º 16
0
void PPPFSM_input
   (
      PCB_PTR        pcb,
            /* [IN] - xCP packet */
      void          *fsm_data
            /* [IN/OUT] - State Machine */
   )
{ /* Body */

#if RTCSCFG_ENABLE_IP4

   PPPFSM_CFG_PTR fsm = fsm_data;
   uint32_t    *stat;
   unsigned char      *inp;
   uint16_t        pcblen, len;

   /*
   ** Parse header (code, id and length).
   ** If packet is too short, drop it.
   */

   stat = NULL;
   fsm->PACKET = pcb;
   inp    = pcb->FRAG[0].FRAGMENT + 2; /* skip the protocol field */
   pcblen = pcb->FRAG[0].LENGTH - 2;

   PPP_mutex_lock(&fsm->MUTEX);
   if (pcblen < CP_HDR_LEN) {
      stat = &fsm->ST_CP_SHORT;
   } else {
      fsm->CODE = *inp++;
      fsm->ID = *inp++;
      len = *inp++ << 8;
      len += *inp++;
      if (len < CP_HDR_LEN) {
         stat = &fsm->ST_CP_SHORT;
      } else if (len > pcblen) {
         stat = &fsm->ST_CP_SHORT;
      } else if (fsm->STATE < PPP_STATE_CLOSED) {
         stat = &fsm->ST_CP_DOWN;
      } /* Endif */
   } /* Endif */

   if (stat) {
      PPP_mutex_unlock(&fsm->MUTEX);
      ++*stat;
      PCB_free(pcb);
      return;
   } /* Endif */

   fsm->LENGTH = len - CP_HDR_LEN;
   fsm->DATA   = inp;
   /*
   ** Action depends on code.
   */
   switch (fsm->CODE) {
   case CP_CODE_CONF_REQ:
      PPPFSM_recvconfreq(fsm, fsm->HANDLE);
      break;

   case CP_CODE_CONF_ACK:
      PPPFSM_recvconfack(fsm);
      break;

   case CP_CODE_CONF_NAK:
      PPPFSM_recvconfnak(fsm, fsm->CALL->recvnak);
      break;

   case CP_CODE_CONF_REJ:
      PPPFSM_recvconfnak(fsm, fsm->CALL->recvrej);
      break;

   case CP_CODE_TERM_REQ:
      PPPFSM_recvtermreq(fsm);
      break;

   case CP_CODE_TERM_ACK:
      PPPFSM_recvtermack(fsm);
      break;

   case CP_CODE_CODE_REJ:
      PPPFSM_recvcoderej(fsm);
      break;

   default:
      if (!fsm->CALL->recvcode || !fsm->CALL->recvcode(fsm)) {
         PPPFSM_sendcoderej(fsm);
      } /* Endif */
      break;
   } /* Endswitch */
   PPP_mutex_unlock(&fsm->MUTEX);

#else

    PCB_free(pcb);

#endif /* RTCSCFG_ENABLE_IP4   */

} /* Endbody */