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 */
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 */
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 */
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); }
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; }
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 */
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++; } }
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 */
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; }
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; }
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */