Ejemplo n.º 1
0
static void PPPFSM_recvtermack
   (
      PPPFSM_CFG_PTR    fsm
            /* [IN/OUT] - State Machine */
   )
{ /* Body */

   switch (fsm->STATE) {
   case PPP_STATE_CLOSING:
   case PPP_STATE_STOPPING:
      PCB_free(fsm->PACKET);
      PPP_send_stop(fsm->HANDLE, fsm->CALL->PROTOCOL);
      fsm->STATE -= 2;  /* Stopping/Closing -> Stopped/Closed */
      break;

   case PPP_STATE_ACK_RCVD:
      PCB_free(fsm->PACKET);
      fsm->STATE = PPP_STATE_REQ_SENT;
      break;

   case PPP_STATE_OPENED:
      if (fsm->CALL->linkdown) {
         fsm->CALL->linkdown(fsm);
      } /* Endif */
      PPPFSM_sendconfreq(fsm, fsm->PACKET);
      fsm->STATE = PPP_STATE_REQ_SENT;
      break;

   default:
      PCB_free(fsm->PACKET);
      break;
   } /* Endswitch */

} /* Endbody */
Ejemplo n.º 2
0
static void PPPFSM_recvconfnak
   (
      PPPFSM_CFG_PTR    fsm,
            /* [IN/OUT] - State Machine */
      bool (_CODE_PTR_ call)(PPPFSM_CFG_PTR)
            /* [IN] - Protocol-specific callback for this packet */
   )
{ /* Body */

   /* Verify the packet */
   if (fsm->ID != fsm->REQID) {
      PCB_free(fsm->PACKET);
      return;

   } else if (!call || !call(fsm)) {
      if (fsm->CODE == CP_CODE_CONF_NAK) {
         ++fsm->ST_CP_BAD_NAK;
      } else {
         ++fsm->ST_CP_BAD_REJ;
      } /* Endif */
      PCB_free(fsm->PACKET);
      return;
   } /* Endif */

   /*
   ** !! Packet consumed here !!
   */
   switch (fsm->STATE) {
   case PPP_STATE_CLOSED:
   case PPP_STATE_STOPPED:
      PPPFSM_sendtermack(fsm, FALSE);
      break;

   case PPP_STATE_REQ_SENT:
   case PPP_STATE_ACK_SENT:
      /* They didn't agree -- try another request */
      PPPFSM_sendconfreq(fsm, fsm->PACKET);
      break;

   case PPP_STATE_ACK_RCVD:
      PPPFSM_sendconfreq(fsm, fsm->PACKET);
      fsm->STATE = PPP_STATE_REQ_SENT;
      break;

   case PPP_STATE_OPENED:
      /* Restart negotiation */
      if (fsm->CALL->linkdown) {
         fsm->CALL->linkdown(fsm);
      } /* Endif */
      PPPFSM_sendconfreq(fsm, fsm->PACKET);
      fsm->STATE = PPP_STATE_REQ_SENT;
      break;

   default:
      PCB_free(fsm->PACKET);
      break;
   } /* Endswitch */

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

   if (fsm->LENGTH < CP_HDR_LEN) {
      ++fsm->ST_CP_SHORT;
      PCB_free(fsm->PACKET);
      return;
   } /* Endif */

   /*
   ** Check if Code-Reject is catastrophic
   **
   ** !! Packet consumed here !!
   */
   if (!fsm->CALL->testcode || !fsm->CALL->testcode(fsm)) {
      if (fsm->STATE == PPP_STATE_ACK_RCVD) {
         fsm->STATE = PPP_STATE_REQ_SENT;
      } /* Endif */
      PCB_free(fsm->PACKET);

   } else {

      switch (fsm->STATE) {
      case PPP_STATE_CLOSING:
         PCB_free(fsm->PACKET);
         PPP_send_stop(fsm->HANDLE, fsm->CALL->PROTOCOL);
         fsm->STATE = PPP_STATE_CLOSED;
         break;

      case PPP_STATE_STOPPING:
      case PPP_STATE_REQ_SENT:
      case PPP_STATE_ACK_RCVD:
      case PPP_STATE_ACK_SENT:
         PCB_free(fsm->PACKET);
         PPP_send_stop(fsm->HANDLE, fsm->CALL->PROTOCOL);
         fsm->STATE = PPP_STATE_STOPPED;
         break;

      case PPP_STATE_OPENED:
         if (fsm->CALL->linkdown) {
            fsm->CALL->linkdown(fsm);
         } /* Endif */
         PPPFSM_sendtermreq(fsm, fsm->PACKET);
         fsm->STATE = PPP_STATE_STOPPING;
         break;

      default:
         PCB_free(fsm->PACKET);
         break;
      } /* Endswitch */
   } /* Endif */

} /* Endbody */
Ejemplo n.º 4
0
static void RTCSPCB_free_internal
   (
      PCB_PTR   inpcb
         /* [IN] packet to free */
   )
{ 
   RTCSPCB_PTR rtcs_pcb = (RTCSPCB_PTR)inpcb->PRIVATE;

   /* Can't free this PCB until all duplicates are freed */
   if (RTCS_sem_trywait(&rtcs_pcb->DUPCOUNT) == RTCS_OK) {
      PCBLOG(("\nPCB: Free_internal: delaying %p", rtcs_pcb));
      return;
   } 

   /* If this PCB is a duplicate, decrement the original's refcount */
   if (rtcs_pcb->DUPPTR) {
      PCBLOG(("\nPCB: Free_internal: about to free %p", rtcs_pcb->DUPPTR));
      RTCSPCB_free(rtcs_pcb->DUPPTR);
      rtcs_pcb->DUPPTR = NULL;
   } 

   /* If this PCB has been forked, don't forget the link layer's PCB */
   if (rtcs_pcb->PCB_ORIG) {
      PCB_free(rtcs_pcb->PCB_ORIG);
      rtcs_pcb->PCB_ORIG = NULL;
   } 

   /* handle the FREE_FRAG_FIELD */
   if (rtcs_pcb->FREE_FRAG_BITFIELD) {
      uint32_t  i;
      for (i = 0; i < RTCSPCB_FRAG_MAX; i++) {
         if (rtcs_pcb->FREE_FRAG_BITFIELD & (1 << i)) {
            _mem_free(rtcs_pcb->PCBPTR->FRAG[i].FRAGMENT);
         } 
      } 
      rtcs_pcb->FREE_FRAG_BITFIELD = 0;
   } 

   if (rtcs_pcb->PCB_FREE) {
      inpcb->FREE    = rtcs_pcb->PCB_FREE;
      inpcb->PRIVATE = rtcs_pcb->PCB_PRIVATE;
      inpcb->FRAG[0] = rtcs_pcb->PCB_BUFFER;
      PCBLOG(("\nPCB: Free_internal: PCB is %p", inpcb));
      PCB_free(inpcb);
   } 

   if (rtcs_pcb->UDP_REQUEST) {
      RTCS_cmd_complete(rtcs_pcb->UDP_REQUEST, RTCS_OK);
      rtcs_pcb->UDP_REQUEST = NULL;
   } 

   RTCS_part_free(rtcs_pcb);

} 
Ejemplo n.º 5
0
int PCBDLL_freeall ()
{
  int i;
  int err = 0;
  PCB *killproc = NULL;

  // Loop through each of the queues
  for ( i = 0; i < TDF_QUEUES; i++ )
    {
      // While there's still stuff in each of the queues
      while ( PRIORITY_QUEUES[i]->next != NULL )
	{
	  // Find the process
	  killproc = PRIORITY_QUEUES[i]->next->contents;
	  // Remove it from the queue
	  err = PCB_remove (killproc);
	  // Deallocate the process
	  PCB_free (killproc);
	}
      // Deallocate the queue
      err = PCBDLL_free( PRIORITY_QUEUES[i] );
    }

  return err;
}
Ejemplo n.º 6
0
void LCP_sendprotrej
   (
      PCB_PTR           pcb,
            /* [IN] - packet to reject */
      PPPFSM_CFG_PTR    fsm
            /* [IN/OUT] - State Machine */
   )
{ /* Body */

#if RTCSCFG_ENABLE_IP4

   PPP_CFG_PTR ppp_ptr = fsm->HANDLE;
   LCP_CFG_PTR lcp_ptr = fsm->PRIVATE;
   unsigned char   *packet, *src, *dst;
   uint16_t     length;
   uint16_t     size = ppp_ptr->SEND_OPTIONS->MRU - CP_HDR_LEN;

   length = pcb->FRAG[0].LENGTH;
   packet = pcb->FRAG[0].FRAGMENT;

   /* Truncate the packet if necessary */
   if (length > size) {
      length = size;
   } /* Endif */

   /* Make room for a Code-Reject header */
   size = length + CP_HDR_LEN;

   /* Copy the received packet (including protocol field) to the */
   /* data portion of the Protocol-Reject                        */
   src = packet + length;
   dst = src + 2 + CP_HDR_LEN;
   while (length--) *--dst = *--src;

   /* Build a Code-Reject packet */
   mqx_htons(packet, PPP_PROT_LCP); packet += 2;
   *packet++ = LCP_CODE_PROT_REJ;
   *packet++ = fsm->CURID;
   fsm->CURID = (fsm->CURID + 1) & 0xFF;
   mqx_htons(packet, size); packet += 2;
   pcb->FRAG[0].LENGTH = size + 2;

   lcp_ptr->ST_LCP_TX_REJECT++;
   PPP_send_one(ppp_ptr, PPP_PROT_LCP, pcb);

#else

    PCB_free(pcb);

#endif /* RTCSCFG_ENABLE_IP4  */

} /* Endbody */
Ejemplo n.º 7
0
static void MACNET_process_tx_bds
   (
         /* [IN] the Ethernet state structure */
      ENET_CONTEXT_STRUCT_PTR  enet_ptr
   )
{ 
   MACNET_CONTEXT_STRUCT_PTR   macnet_context_ptr = (MACNET_CONTEXT_STRUCT_PTR) enet_ptr->MAC_CONTEXT_PTR;
   uint_16                     tx_status;
   

   /* Dequeue all transmitted frames */
   while (macnet_context_ptr->AvailableTxBDs < macnet_context_ptr->NumTxBDs) {
      VENET_BD_STRUCT_PTR bd_ptr = &macnet_context_ptr->MACNET_TX_RING_PTR[macnet_context_ptr->LastTxBD];

      _DCACHE_INVALIDATE_MBYTES((pointer)bd_ptr, sizeof(ENET_BD_STRUCT));  

      if (bd_ptr->CONTROL & HOST_TO_BE_SHORT_CONST(ENET_BD_ETHER_TX_READY)) {
         break;
      } /* Endif */

      macnet_context_ptr->TxErrors |= SHORT_BE_TO_HOST(bd_ptr->CONTROL);
      tx_status = macnet_context_ptr->TxErrors;

      /* Record statistics for each frame (not each buffer) */
      if (tx_status & ENET_BD_ETHER_TX_LAST) {
         PCB_PTR pcb_ptr;
         macnet_context_ptr->TxErrors = 0;

         ENET_INC_STATS(COMMON.ST_TX_TOTAL);

         pcb_ptr = macnet_context_ptr->TxPCBS_PTR[macnet_context_ptr->LastTxBD];
         PCB_free(pcb_ptr);
      } 

      if (macnet_context_ptr->FREE_TX_SMALL & (1<<macnet_context_ptr->LastTxBD)) {
         ENET_Enqueue_Buffer((pointer *) &macnet_context_ptr->SMALL_BUFFERS, (pointer)LONG_BE_TO_HOST((uint_32)(bd_ptr->BUFFER)));
         macnet_context_ptr->FREE_TX_SMALL &= ~(1<<macnet_context_ptr->LastTxBD);
      } else if (macnet_context_ptr->FREE_TX & (1<<macnet_context_ptr->LastTxBD)) {
         ENET_Enqueue_Buffer((pointer *) &macnet_context_ptr->TX_BUFFERS, (pointer)LONG_BE_TO_HOST((uint_32)(bd_ptr->BUFFER)));
         macnet_context_ptr->FREE_TX &= ~(1<<macnet_context_ptr->LastTxBD);
      }      
      BD_INC(macnet_context_ptr->LastTxBD,macnet_context_ptr->NumTxBDs);
      macnet_context_ptr->AvailableTxBDs++;

   } 
} 
Ejemplo n.º 8
0
void IPCP_recv
   (
      PCB_PTR     pcb,
            /* [IN] received packet */
      pointer     handle
            /* [IN] IPCP configuration */
   )
{ /* Body */
   IP_IF_PTR            if_ptr = handle;
   RTCSPCB_PTR          packet;
   uint_32              error;

   IF_IPIF_STATS_ENABLED(if_ptr->STATS.COMMON.ST_RX_TOTAL++);
   IF_IPIF_STATS_ENABLED(if_ptr->STATS.ST_RX_OCTETS += pcb->FRAG[0].LENGTH);
   IF_IPIF_STATS_ENABLED(if_ptr->STATS.ST_RX_UNICAST++);

   packet = RTCSPCB_alloc_recv(pcb);
   if (packet == NULL) {
      IF_IPIF_STATS_ENABLED(if_ptr->STATS.COMMON.ST_RX_MISSED++);
      PCB_free(pcb);
      return;
   } /* Endif */

   //RTCSLOG_PCB_ALLOC(packet);

   error = RTCSPCB_next(packet, 2);
   if (error) {
      IF_IPIF_STATS_ENABLED(if_ptr->STATS.COMMON.ST_RX_ERRORS++);
      IF_IPIF_STATS_ENABLED(RTCS_seterror(&if_ptr->STATS.ERR_RX, error, (uint_32)packet));
      RTCSLOG_PCB_FREE(packet, error);
      RTCSPCB_free(packet);
      return;
   } /* Endif */

   RTCSLOG_PCB_READ(packet, RTCS_LOGCTRL_IFTYPE(IPIFTYPE_PPP), 0);

   packet->TYPE = RTCSPCB_TYPE_ONLYCAST;
   packet->IFSRC = if_ptr;

   if (!RTCSCMD_service(packet, IP_service)) {
      IF_IPIF_STATS_ENABLED(if_ptr->STATS.COMMON.ST_RX_MISSED++);
      RTCSLOG_PCB_FREE(packet, RTCS_OK);
      RTCSPCB_free(packet);
   } /* Endif */

} /* Endbody */
Ejemplo n.º 9
0
uint32_t ENET_send
   (
      /* [IN] the Ethernet state structure */
      _enet_handle   handle,

      /* [IN] the packet to send */
      PCB_PTR        packet,

      /* [IN] the protocol */
      uint16_t        type,

      /* [IN] the destination Ethernet address */
      _enet_address  dest,

      /* [IN] optional flags, zero = default */
      uint32_t        flags
   )
{ 
   ENET_CONTEXT_STRUCT_PTR  enet_ptr = (ENET_CONTEXT_STRUCT_PTR)handle;
   ENET_HEADER_PTR         packet_ptr;
   unsigned char               *type_ptr;
   PCB_FRAGMENT_PTR        frag_ptr;
   uint32_t                 swhdr, size, frags;
   uint32_t                 error;
   _KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data);
   
   _KLOGM(_GET_KERNEL_DATA(kernel_data));
   _KLOGE6(KLOG_ENET_send, handle, packet, type, dest, flags);

   if (flags & ENET_OPT_8021QTAG) {
       swhdr = ENET_FRAMESIZE_HEAD_VLAN;
   } else {
       swhdr = ENET_FRAMESIZE_HEAD;
   } 

   /*
   ** Make sure the first fragment is long enough for the Ethernet
   ** frame header.  This isn't strictly necessary, but it's impractical
   ** to split a 14-26 byte header over multiple fragments.
   */
#if MQX_CHECK_ERRORS
   if (packet->FRAG[0].LENGTH < swhdr) {
      ENET_INC_STATS(COMMON.ST_TX_DISCARDED);
      error = ENETERR_SEND_SHORT;
      goto ERROR;
   }
#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 = frags = 0;
   for (frag_ptr = packet->FRAG; frag_ptr->LENGTH; frag_ptr++) {
#if MQX_CHECK_ERRORS
      if (frag_ptr->LENGTH > enet_ptr->MaxTxFrameSize) {   
         ENET_INC_STATS(COMMON.ST_TX_DISCARDED);
         error = ENETERR_SEND_LONG;
         goto ERROR;
      } 
#endif
      size += frag_ptr->LENGTH;
      frags++;
   } 

   /*
   ** Make sure that the total sum of the fragments doesn't exceed
   ** a maximum packet length.
   */
#if MQX_CHECK_ERRORS
   if (size > enet_ptr->MaxTxFrameSize) {
      ENET_INC_STATS(COMMON.ST_TX_DISCARDED);
      error = ENETERR_SEND_LONG;
      goto ERROR;
   } 
#endif

   /*
   ** Everything checks out -- fill in the header.
   */
   packet_ptr = (ENET_HEADER_PTR)packet->FRAG[0].FRAGMENT;
   htone(packet_ptr->DEST, dest);
   htone(packet_ptr->SOURCE, enet_ptr->ADDRESS);
   type_ptr = packet_ptr->TYPE;

   if (flags & ENET_OPT_8021QTAG) {
      ENET_8021QTAG_HEADER_PTR tag_ptr = (ENET_8021QTAG_HEADER_PTR)(type_ptr+2);
      uint16_t tag;
      tag = ENET_GETOPT_8021QPRIO(flags) << 13;
      mqx_htons(type_ptr, ENETPROT_8021Q);
      mqx_htons(tag_ptr->TAG, tag);
      type_ptr = tag_ptr->TYPE;
   } 

   if (flags & ENET_OPT_8023) {
      ENET_8022_HEADER_PTR llc_ptr = (ENET_8022_HEADER_PTR)(type_ptr+2);
      (void)mqx_htons(type_ptr, size - swhdr);
      mqx_htonc(llc_ptr->DSAP, 0xAA);
      mqx_htonc(llc_ptr->SSAP, 0xAA);
      mqx_htonc(llc_ptr->COMMAND, 0x03);
      mqx_htonc(&llc_ptr->OUI[0], 0x00);
      mqx_htonc(&llc_ptr->OUI[1], 0x00);
      mqx_htonc(&llc_ptr->OUI[2], 0x00);
      type_ptr = llc_ptr->TYPE;
   } 

   mqx_htons(type_ptr, type);

   /*
   ** This function can be called from any context, and it needs mutual
   ** exclusion with itself, and with ENET_ISR().
   */
   ENET_lock_context(enet_ptr);
   error = (*enet_ptr->PARAM_PTR->ENET_IF->MAC_IF->SEND)(handle, packet, size, frags, flags);
   ENET_unlock_context(enet_ptr);

   if (error) {
   ERROR:
      PCB_free(packet);
   }
   
   _KLOGX4(KLOG_ENET_send, handle, packet, error);
   
   return error;
}  
Ejemplo n.º 10
0
uint32_t ENET_send_raw
   (
      /* [IN] the Ethernet state structure */
      _enet_handle   handle,

      /* [IN] the packet to send */
      PCB_PTR        packet
   )
{ /* Body */
   ENET_CONTEXT_STRUCT_PTR    enet_ptr = (ENET_CONTEXT_STRUCT_PTR)handle;
   PCB_FRAGMENT_PTR           frag_ptr;
   uint32_t                    size, frags;
   uint32_t                    error;

   /*
   ** 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 = frags = 0;
   for (frag_ptr = packet->FRAG; frag_ptr->LENGTH; frag_ptr++) {
#if MQX_CHECK_ERRORS
      if (frag_ptr->LENGTH > enet_ptr->MaxTxFrameSize) {   
         ENET_INC_STATS(COMMON.ST_TX_DISCARDED);
         error = ENETERR_SEND_LONG;
         goto ERROR;
      } 
#endif
      size += frag_ptr->LENGTH;
      frags++;
   } 

   /*
   ** Make sure that the total sum of the fragments doesn't exceed
   ** a maximum packet length.
   */
#if MQX_CHECK_ERRORS
   if (size > enet_ptr->MaxTxFrameSize) {
      ENET_INC_STATS(COMMON.ST_TX_DISCARDED);
      error = ENETERR_SEND_LONG;
      goto ERROR;
   } 
#endif

   /*
   ** This function can be called from any context, and it needs mutual
   ** exclusion with itself, and with ENET_ISR().
   */
   ENET_lock_context(enet_ptr);
   error = (*enet_ptr->PARAM_PTR->ENET_IF->MAC_IF->SEND)(handle, packet, size, frags, 0);
   ENET_unlock_context(enet_ptr);

   if (error) {
   ERROR:
      PCB_free(packet);
   }  

   return error;

}  
Ejemplo n.º 11
0
static RTCSPCB_PTR IPREASM_reasm_dgram
   (
      IP_DGRAM_PTR   dgram    /* [IN] the dgram descriptor */
   )
{ /* Body */
   RTCSPCB_PTR outpcb;
   PCB_PTR     bpcb;
   PCB_FRAGMENT      *pcb_frag_ptr;
   unsigned char   *data;
   uint32_t     iphlen  = (mqx_ntohc(dgram->header.IP4.IPH.VERSLEN) & 0xF) << 2;
   uint32_t     ip_totlen = iphlen + dgram->TOTLEN;

   bpcb = RTCS_mem_alloc_system(sizeof(PCB) + sizeof(PCB_FRAGMENT) + ip_totlen);
   if (!bpcb) {
      return NULL;
   } /* Endif */

   data = (unsigned char *)bpcb + sizeof(PCB) + sizeof(PCB_FRAGMENT);
   bpcb->FREE    = (void(_CODE_PTR_)(PCB_PTR))_mem_free;
   bpcb->PRIVATE = NULL;
 
   pcb_frag_ptr = bpcb->FRAG;
   pcb_frag_ptr->LENGTH   = ip_totlen;
   pcb_frag_ptr->FRAGMENT = data;
   pcb_frag_ptr++;
   pcb_frag_ptr->LENGTH   = 0;
   pcb_frag_ptr->FRAGMENT = NULL;

   /* Copy the IP header with options */
   mqx_htons(dgram->header.IP4.IPH.FRAGMENT, 0);
   _mem_copy(&dgram->header.IP4.IPH, data, iphlen);
   data += iphlen;

   /*
   ** At this point, we really should update the LENGTH
   ** and CHECKSUM fields in the new IP header, but we
   ** don't actually need to, because this datagram is
   ** going straight to IPLOCAL_service, which doesn't
   ** check these things.
   */

   /* Copy the stored data in the new packet */
   IPREASM_blk_read_all(dgram, data, dgram->TOTLEN);

   /* Put it in an RTCSPCB */
   outpcb = RTCSPCB_alloc_recv(bpcb);
   if (outpcb == NULL) {
      PCB_free(bpcb);
      return NULL;
   } /* Endif */
   //RTCSLOG_PCB_ALLOC(bpcb);
   outpcb->IFSRC           = dgram->IFSRC;
   outpcb->TYPE            = dgram->TYPE;
   outpcb->LINK_OPTIONS.RX = dgram->LINKOPT;
   RTCSPCB_DATA_NETWORK(outpcb) = RTCSPCB_DATA(outpcb);
   RTCSPCB_SET_TRANS_PROTL(outpcb, dgram->header.IP4.PROTO);
   RTCSPCB_SET_TRANS_DELTA(outpcb, iphlen);

   /* Delete the local structure */
   IPREASM_del_dgram(dgram);

   return outpcb;

} /* Endbody */
Ejemplo n.º 12
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.º 13
0
static void PPPFSM_recvconfreq
   (
      PPPFSM_CFG_PTR    fsm,
            /* [IN/OUT] - State Machine */
      _ppp_handle       handle
            /* [IN] - the PPP state structure */
   )
{ /* Body */
   PPP_CFG_PTR    ppp_ptr = handle;
   uint32_t        size;

   switch (fsm->STATE) {
   case PPP_STATE_CLOSED:
      PPPFSM_sendtermack(fsm, FALSE);
      return;
   case PPP_STATE_CLOSING:
   case PPP_STATE_STOPPING:
      PCB_free(fsm->PACKET);
      return;

   case PPP_STATE_OPENED:
      /* Go down and restart negotiation */
      if (fsm->CALL->linkdown) {
         fsm->CALL->linkdown(fsm);
      } /* Endif */
      PPPFSM_sendconfreq(fsm, NULL);
      fsm->STATE = PPP_STATE_REQ_SENT;
      break;

   case PPP_STATE_STOPPED:
      /* Negotiation started by our peer */
      PPPFSM_sendconfreq(fsm, NULL);
      fsm->STATE = PPP_STATE_REQ_SENT;
      break;
   } /* Endswitch */

   /*
   ** Pass the requested configuration options
   ** to protocol-specific code for checking.
   **
   ** !! Packet consumed here !!
   */
   if (fsm->CALL->recvreq) {    /* Check CI */
      size = fsm->CALL->recvreq(fsm, fsm->NAKS >= _PPP_MAX_CONF_NAKS);
      PPPFSM_buildheader(fsm, fsm->PACKET, 0, TRUE, size);
      PPP_send_one(ppp_ptr, fsm->CALL->PROTOCOL, fsm->PACKET);
   } else if (fsm->LENGTH) {
      PPPFSM_sendconfrep(fsm, CP_CODE_CONF_REJ);
   } else {
      PPPFSM_sendconfrep(fsm, CP_CODE_CONF_ACK);
   } /* Endif */

   if (fsm->CODE == CP_CODE_CONF_ACK) {
      if (fsm->STATE == PPP_STATE_ACK_RCVD) {
         /* Inform upper layers */
         if (fsm->CALL->linkup) {
            if (!fsm->CALL->linkup(fsm)) {
               PPPFSM_sendtermreq(fsm, NULL);
               fsm->STATE = PPP_STATE_CLOSING;
               return;
            } /* Endif */
         } /* Endif */
         fsm->STATE = PPP_STATE_OPENED;
         PPP_send_stop(ppp_ptr, fsm->CALL->PROTOCOL);
      } else {
         fsm->STATE = PPP_STATE_ACK_SENT;
      } /* Endif */
      fsm->NAKS = 0;

   } else { /* We sent a NAK or a REJ */
      if (fsm->STATE != PPP_STATE_ACK_RCVD) {
         fsm->STATE = PPP_STATE_REQ_SENT;
      } /* Endif */
      if (fsm->CODE == CP_CODE_CONF_NAK ) {
         ++fsm->NAKS;
      } /* Endif */
   } /* Endif */
} /* Endbody */
Ejemplo n.º 14
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 */
Ejemplo n.º 15
0
void PAP_input
   (
      PCB_PTR        pcb,
            /* [IN] - PAP packet */
      _ppp_handle    handle
            /* [IN] - the PPP state structure */
   )
{ /* Body */
   PPP_CFG_PTR    ppp_ptr = handle;
   PAP_DATA_PTR   pap_ptr = &ppp_ptr->PAP_STATE;
   PPP_SECRET_PTR secret;
   uchar_ptr      inp = pcb->FRAG[0].FRAGMENT + 2;
   uchar_ptr      idp, pwp;
   uchar          code, id;
   uchar          idlen, pwlen;
   uint_16        len;
   boolean        delay = FALSE;

   /*
   ** Parse header (code, id and length).
   ** If packet too short, drop it.
   */
   if (pcb->FRAG[0].LENGTH < 2 + PAP_HDR_LEN) {
      pap_ptr->ST_PAP_SHORT++;
      PCB_free(pcb);
      return;
   } /* Endif */

   code = *inp++;
   id = *inp++;
   len = *inp++ << 8;
   len += *inp++;

   if ((len < PAP_HDR_LEN) || (len > pcb->FRAG[0].LENGTH - 2)) {
      pap_ptr->ST_PAP_SHORT++;
      PCB_free(pcb);
      return;
   } /* Endif */
   len -= PAP_HDR_LEN;

   switch (code) {

   case PAP_CODE_AUTH_REQ:
      switch (pap_ptr->SERVER_STATE) {
      case PAP_STATE_INITIAL:

         /* Parse the peer id and password */
         idp = inp;
         idlen = *idp++;
         pwp = idp + idlen;
         pwlen = *pwp++;
         if (len < idlen + pwlen + 2) {
            pap_ptr->ST_PAP_SHORT++;
            PCB_free(pcb);
            break;
         } /* Endif */

         /* Match id/password pair against the secrets table */
/* Start CR 2207 */
         secret = PPP_SECRET(ppp_ptr,_PPP_PAP_RSECRETS);
/* End CR 2207 */
         for (;;) {
            if ((secret->PPP_ID_LENGTH == 0)
             && (secret->PPP_PW_LENGTH == 0)) {
               pap_ptr->SERVER_STATE = PAP_STATE_AUTH_NAK;
               PAP_fail(handle);
               delay = TRUE;
               break;
            } /* Endif */
            if ((secret->PPP_ID_LENGTH == idlen)
             && (secret->PPP_PW_LENGTH == pwlen)
             && (memcmp(secret->PPP_ID_PTR, idp, idlen) == 0)
             && (memcmp(secret->PPP_PW_PTR, pwp, pwlen) == 0)) {
               pap_ptr->SERVER_STATE = PAP_STATE_AUTH_ACK;
               PAP_up(handle);
               break;
            } /* Endif */
            secret++;
         } /* Endfor */

         /* fall through */
      case PAP_STATE_AUTH_ACK:
      case PAP_STATE_AUTH_NAK:
         /* Build an Auth-Ack or Auth-Nak reply */
         inp = pcb->FRAG[0].FRAGMENT + 2;
         *inp++ = pap_ptr->SERVER_STATE;
         inp++;                              /* Keep same ID */
         *inp++ = 0;
         *inp++ = 5;
         *inp++ = 0;
         pcb->FRAG[0].LENGTH = 7;
         if (delay) {
            PPP_send_rexmit(ppp_ptr, PPP_PROT_PAP, pcb, 1, PAP_close, handle);
         } else {
            PPP_send_one(ppp_ptr, PPP_PROT_PAP, pcb);
         } /* Endif */
         break;

      default:
         pap_ptr->ST_PAP_NOAUTH++;
         PCB_free(pcb);
         break;
      } /* Endswitch */
      break;

   case PAP_CODE_AUTH_ACK:
       pap_ptr->CLIENT_STATE = PAP_STATE_AUTH_ACK;
       PAP_up(handle);
   case PAP_CODE_AUTH_NAK:
      if (pap_ptr->CLIENT_STATE != PAP_STATE_AUTH_ACK) {
         pap_ptr->CLIENT_STATE = PAP_STATE_AUTH_NAK;
      } /* Endif */
      
      if (pap_ptr->CLIENT_STATE != PAP_STATE_INITIAL && pap_ptr->CLIENT_STATE != PAP_STATE_AUTH_ACK) {
         pap_ptr->ST_PAP_NOREQ++;
      } else if (id != pap_ptr->CURID) {
         pap_ptr->ST_PAP_ID++;
      } else if (len < 1) {
         pap_ptr->ST_PAP_SHORT++;
      } else if (--len < *inp++) {
         pap_ptr->ST_PAP_SHORT++;
      } else {
         /* All is well -- stop send Auth-Req's */
         PPP_send_stop(ppp_ptr, PPP_PROT_PAP);
      } /* Endif */
      PCB_free(pcb);
      break;

   default:
      pap_ptr->ST_PAP_CODE++;
      PCB_free(pcb);
      break;
   } /* Endswitch */

} /* Endbody */
Ejemplo n.º 16
0
static bool LCP_recvextcode
   (
      PPPFSM_CFG_PTR    fsm
            /* [IN] - State Machine */
   )
{ /* Body */
   PPP_CFG_PTR ppp_ptr = fsm->HANDLE;
   LCP_CFG_PTR lcp_ptr = fsm->PRIVATE;
   PPP_CALL_INTERNAL_PTR call_ptr = &ppp_ptr->LCP_CALL[PPP_CALL_ECHO_REPLY];

   switch (fsm->CODE) {
   case LCP_CODE_PROT_REJ:
      lcp_ptr->ST_LCP_RX_REJECT++;

      /*
      ** We should notify the rejected protocol, but there
      ** currently isn't any way to do this.  What we'll do
      ** instead is to send a STOP message to the Tx task on
      ** behalf of the protocol.
      **
      ** This will usually be sufficient, since the rejected
      ** protocol isn't likely to send another packet until
      ** either it receives a packet (in which case it's OK to
      ** reply) or the retransmission timer kicks in (which
      ** we're about to disable).
      **
      ** Thus, this will effectively stop the rejected protocol.
      */

      if (fsm->LENGTH >= 2) {
         uint16_t protocol = mqx_ntohs(fsm->DATA);
         PPP_send_stop(ppp_ptr, protocol);
      } /* Endif */
      PCB_free(fsm->PACKET);
      break;

   case LCP_CODE_ECHO_REQ:
      lcp_ptr->ST_LCP_RX_ECHO++;
      if (fsm->STATE < PPP_STATE_OPENED) {
         PCB_free(fsm->PACKET);
      } else {
         mqx_htonc(fsm->DATA - CP_HDR_LEN, LCP_CODE_ECHO_REP);
         mqx_htonl(fsm->DATA, 0);                      /* Set magic field to 0 */
         lcp_ptr->ST_LCP_TX_REPLY++;
         PPP_send_one(ppp_ptr, PPP_PROT_LCP, fsm->PACKET);
      } /* Endif */
      break;

   case LCP_CODE_ECHO_REP:
      lcp_ptr->ST_LCP_RX_REPLY++;
      if (call_ptr->CALLBACK) {
         call_ptr->CALLBACK(call_ptr->PARAM, fsm->ID, fsm->PACKET);
      } /* Endif */
      PCB_free(fsm->PACKET);
      break;

   case LCP_CODE_DISC_REQ:
      lcp_ptr->ST_LCP_RX_DISCARD++;
      PCB_free(fsm->PACKET);
      break;

   default:
      return FALSE;
   } /* Endswitch */

   return TRUE;
} /* Endbody */
Ejemplo n.º 17
0
static void _iopcb_hdlc_write
   (
   _iopcb_handle      handle,
   /* [IN] - the handle */
   PCB_PTR            pcb_ptr,
   /* [IN] - the packet */
   uint_32            flags
   /* [IN] - the flags */
   )
{ /* Body */
   RTCS_HDLC_MESSAGE_STRUCT_PTR msg_ptr;
   HDLCIO_STRUCT_PTR            hdlcio_ptr = (HDLCIO_STRUCT_PTR)((void _PTR_)handle);
   uint_32                      data_length = 0;
   uint_32                      i = 0;
   uint_32                      j = 0;
   _RTCS_queueid                qid;

   while (pcb_ptr->FRAG[i].LENGTH && (data_length <= RTCS_HDLC_MESSAGE_SIZE)) {
      data_length += pcb_ptr->FRAG[i].LENGTH;
      i++;
   } /* Endwhile */
   i = 0;

   if ( data_length > RTCS_HDLC_MESSAGE_SIZE ) {
      PCB_free(pcb_ptr);
      return;
   }/* Endif */

   hdlcio_ptr->STATS.COMMON.ST_TX_TOTAL++;
   msg_ptr = (RTCS_HDLC_MESSAGE_STRUCT_PTR)RTCS_msg_alloc(hdlcio_ptr->POOL_ID);
   if (msg_ptr == NULL) {
      /* Free the PCB and return */
      hdlcio_ptr->STATS.COMMON.ST_TX_MISSED++;
      PCB_free(pcb_ptr);
      return;
   } /* Endif */

   /* assemble message to send */
   qid = RTCS_msgq_get_id(0, hdlcio_ptr->CHANNEL_Q);
   msg_ptr->HDLC_HEADER.HEADER.TARGET_QID = qid;
   msg_ptr->HDLC_HEADER.HEADER.SOURCE_QID = hdlcio_ptr->QID;
   msg_ptr->HDLC_HEADER.HEADER.SIZE = sizeof(RTCS_HDLC_MESSAGE_STRUCT)
      + data_length + 2;
   msg_ptr->HDLC_HEADER.PACKET_SIZE = data_length + 2;

   /* Add address and control bytes */
   msg_ptr->DATA[0] = 0xFF;
   msg_ptr->DATA[1] = 0x03;
   j+=2;



   while (pcb_ptr->FRAG[i].LENGTH) {
      RTCS_memcopy(pcb_ptr->FRAG[i].FRAGMENT, &msg_ptr->DATA[j],
         pcb_ptr->FRAG[i].LENGTH);
      j += pcb_ptr->FRAG[i].LENGTH;
      i++;
   } /* Endwhile */

   PCB_free(pcb_ptr);

   if (!RTCS_msgq_send(msg_ptr, hdlcio_ptr->POOL_ID)) {
      hdlcio_ptr->STATS.COMMON.ST_TX_MISSED++;
   } /* Endif */ ;

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

   /* Verify the packet */
   if (fsm->ID != fsm->REQID) {
      PCB_free(fsm->PACKET);
      return;
   } else if (fsm->CALL->recvack) {
      if (!fsm->CALL->recvack(fsm)) {
         ++fsm->ST_CP_BAD_ACK;
         PCB_free(fsm->PACKET);
         return;
      } /* Endif */
   } else if (fsm->LENGTH) {
      ++fsm->ST_CP_BAD_ACK;
      PCB_free(fsm->PACKET);
      return;
   } /* Endif */

   /*
   ** !! Packet consumed here !!
   */
   switch (fsm->STATE) {
   case PPP_STATE_CLOSED:
   case PPP_STATE_STOPPED:
      
      PPPFSM_sendtermack(fsm, FALSE);
      break;

   case PPP_STATE_REQ_SENT:
      /* Restart retransmissions */
      fsm->STATE = PPP_STATE_ACK_RCVD;
      PCB_free(fsm->PACKET);
      PPP_send_restart(fsm->HANDLE, fsm->CALL->PROTOCOL);
      break;

   case PPP_STATE_ACK_RCVD:
      PPPFSM_sendconfreq(fsm, fsm->PACKET);
      fsm->STATE = PPP_STATE_REQ_SENT;
      break;

   case PPP_STATE_ACK_SENT:
      /* Inform upper layers */
      if (fsm->CALL->linkup) {
         if (!fsm->CALL->linkup(fsm)) {
            PPPFSM_sendtermreq(fsm, fsm->PACKET);
            fsm->STATE = PPP_STATE_CLOSING;
            return;
         } /* Endif */
      } /* Endif */
      fsm->STATE = PPP_STATE_OPENED;
      PCB_free(fsm->PACKET);
      PPP_send_stop(fsm->HANDLE, fsm->CALL->PROTOCOL);
      break;

   case PPP_STATE_OPENED:
      /* Restart negotiation */
      if (fsm->CALL->linkdown) {
         fsm->CALL->linkdown(fsm);
      } /* Endif */
      PPPFSM_sendconfreq(fsm, fsm->PACKET);
      fsm->STATE = PPP_STATE_REQ_SENT;
      break;

   default:
      PCB_free(fsm->PACKET);
      break;
   } /* Endswitch */

} /* Endbody */
Ejemplo n.º 19
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.º 20
0
void CHAP_input
   (
      PCB_PTR        pcb,
            /* [IN] - CHAP packet */
      _ppp_handle    handle
            /* [IN] - the PPP state structure */
   )
{ /* Body */
   PPP_CFG_PTR    ppp_ptr = handle;
   CHAP_DATA_PTR  chap_ptr = &ppp_ptr->CHAP_STATE;
   PPP_SECRET_PTR secret;
   uchar_ptr      inp = pcb->FRAG[0].FRAGMENT + 2;
   uchar_ptr      valp, idp;
   uchar          code, id;
   uchar          vallen, idlen, namelen;
   uint_16        len;
   boolean        delay = FALSE;

   /*
   ** Parse header (code, id and length).
   ** If packet too short, drop it.
   */
   if (pcb->FRAG[0].LENGTH < 2 + CHAP_HDR_LEN) {
      chap_ptr->ST_CHAP_SHORT++;
      PCB_free(pcb);
      return;
   } /* Endif */

   code = *inp++;
   id = *inp++;
   len = *inp++ << 8;
   len += *inp++;

   if ((len < CHAP_HDR_LEN) || (len > pcb->FRAG[0].LENGTH - 2)) {
      chap_ptr->ST_CHAP_SHORT++;
      PCB_free(pcb);
      return;
   } /* Endif */
   len -= CHAP_HDR_LEN;

   /*
   ** For Challenge and Response packets, also parse the
   ** value and name fields.
   */
   if ((code == CHAP_CODE_CHALLENGE) || (code == CHAP_CODE_RESPONSE)) {

      if (len < 1) {
         chap_ptr->ST_CHAP_SHORT++;
         PCB_free(pcb);
         return;
      } /* Endif */
      valp = inp;
      vallen = *valp++;
      len--;

      if (len < vallen) {
         chap_ptr->ST_CHAP_SHORT++;
         PCB_free(pcb);
         return;
      } /* Endif */
      idp = valp + vallen;
      idlen = len - vallen;

   } /* Endif */

   switch (code) {

   case CHAP_CODE_CHALLENGE:

      if (chap_ptr->CLIENT_STATE != CHAP_STATE_INITIAL) {
         chap_ptr->ST_CHAP_NOAUTH++;
         PCB_free(pcb);
         break;
      } /* Endif */

      /* OK -- Generate a Response packet */
      /* Start CR 2207 */
      secret = PPP_SECRET(ppp_ptr,_PPP_CHAP_LSECRETS);
      /* End CR 2207 */
      inp = pcb->FRAG[0].FRAGMENT + 2;
      *inp++ = CHAP_CODE_RESPONSE;
      inp++;                           /* Keep same ID */
      /* Start CR 2207 */
      namelen = strlen(PPP_SECRET(ppp_ptr,_PPP_CHAP_LNAME));
      /* End CR 2207 */
      len = CHAP_HDR_LEN + 1 + 16 + namelen;
      *inp++ = (len >> 8) & 0xFF;
      *inp++ =  len       & 0xFF;
      *inp++ = 16;
      for (;;) {
         if ((secret->PPP_ID_LENGTH == 0)
          && (secret->PPP_PW_LENGTH == 0)) {
            /* Couldn't find a secret for this peer */
            chap_ptr->ST_CHAP_NOPW++;
            PPP_MD5(inp, (uint_32)1, &id,       /* id */
                         (uint_32)vallen, valp, /* challenge */
                         (uint_32)0);
            break;
         } /* Endif */
         if ((secret->PPP_ID_LENGTH == idlen)
          && (memcmp(secret->PPP_ID_PTR, idp, idlen) == 0)) {
            /* Found a secret; send response */
            PPP_MD5(inp, (uint_32)1, &id,                /* id */
                         (uint_32)secret->PPP_PW_LENGTH, /* secret */
                         secret->PPP_PW_PTR,
                         (uint_32)vallen, valp,          /* challenge */
                         (uint_32)0);
            break;
         } /* Endif */
         secret++;
      } /* Endfor */
      inp += 16;
      /* Start CR 2207 */
      PPP_memcopy(PPP_SECRET(ppp_ptr,_PPP_CHAP_LNAME), inp, namelen);
      /* End CR 2207 */
      pcb->FRAG[0].LENGTH = len + 2;
      PPP_send_one(ppp_ptr, PPP_PROT_CHAP, pcb);
      break;

   case CHAP_CODE_RESPONSE:

      switch (chap_ptr->SERVER_STATE) {
      case CHAP_STATE_INITIAL:

         /* Check the ID against our last challenge */
         if (id != chap_ptr->CURID) {
            chap_ptr->ST_CHAP_ID++;
            PCB_free(pcb);
            break;
         } /* Endif */

         /* Stop the challenge, whether or not the response is correct */
         PPP_send_stop(ppp_ptr, PPP_PROT_CHAP);

         chap_ptr->SERVER_STATE = CHAP_STATE_FAILURE;

         if (vallen != 16) {
            delay = TRUE;
            CHAP_fail(handle);

         } else {
            /* Search for name in the secrets table */
            /* Start CR 2207 */
            secret = PPP_SECRET(ppp_ptr,_PPP_CHAP_RSECRETS);
            /* End CR 2207 */
            for (;;) {
               if ((secret->PPP_ID_LENGTH == 0)
                && (secret->PPP_PW_LENGTH == 0)) {
                     /* Couldn't find a secret for this peer */
                  delay = TRUE;
                  CHAP_fail(handle);
                  break;
               } /* Endif */
               if ((secret->PPP_ID_LENGTH == idlen)
                && (memcmp(secret->PPP_ID_PTR, idp, idlen) == 0)) {
                     /* Found a secret; compute hash */
                  uchar digest[16];

                  PPP_MD5(digest, (uint_32)1, &id,                /* id */
                                  (uint_32)secret->PPP_PW_LENGTH, /* secret */
                                  secret->PPP_PW_PTR,
                                  (uint_32)CHAP_CHALLENGE_LEN,    /* challenge */
                                  chap_ptr->MD5,
                                  (uint_32)0);

                  if (memcmp(digest, valp, vallen) == 0) {
                     chap_ptr->SERVER_STATE = CHAP_STATE_SUCCESS;
                     CHAP_up(handle);
                  } else {
                     delay = TRUE;
                     CHAP_fail(handle);
                  } /* Endif */
                  break;
               } /* Endif */
               secret++;
            } /* Endfor */
         } /* Endif */

         /* fall through */
      case CHAP_STATE_SUCCESS:
      case CHAP_STATE_FAILURE:
         /* Build a Success or Failure reply */
         inp = pcb->FRAG[0].FRAGMENT + 2;
         *inp++ = chap_ptr->SERVER_STATE;
         inp++;                              /* Keep same ID */
         *inp++ = 0;
         *inp++ = 4;
         pcb->FRAG[0].LENGTH = 6;
         if (delay) {
            PPP_send_rexmit(ppp_ptr, PPP_PROT_CHAP, pcb, 1, CHAP_close, handle);
         } else {
            PPP_send_one(ppp_ptr, PPP_PROT_CHAP, pcb);
         } /* Endif */
         break;

      default:
         chap_ptr->ST_CHAP_NOCHAL++;
         PCB_free(pcb);
         break;
      } /* Endswitch */
      break;

   case CHAP_CODE_SUCCESS:
       /* Authentication success */
       chap_ptr->CLIENT_STATE = CHAP_STATE_SUCCESS;
       CHAP_up(handle);
   case CHAP_CODE_FAILURE:
       /* Authentication failure */
      if (chap_ptr->CLIENT_STATE != CHAP_STATE_SUCCESS)
      {
          /* Change client state when authenticate failure */
          chap_ptr->CLIENT_STATE = CHAP_STATE_FAILURE;
          if (chap_ptr->CLIENT_STATE != CHAP_STATE_INITIAL)
          {
             chap_ptr->ST_CHAP_NOAUTH++;
          }
          CHAP_fail(handle);
      } /* Endif */
      PCB_free(pcb);
      break;

   default:
      chap_ptr->ST_CHAP_CODE++;
      PCB_free(pcb);
      break;
   } /* Endswitch */

} /* Endbody */