void BOOTP_open ( TCPIP_PARM_BOOTP *parms ) { /* Body */ IP_IF_PTR if_ptr = (IP_IF_PTR)parms->handle; BOOTP_CFG_PTR bootp = (BOOTP_CFG_PTR) &parms->config; uint32_t error; error = BOOT_open(BOOT_service); if (error) { RTCSCMD_complete(parms, error); return; } /* Endif */ if_ptr->BOOTFN = BOOTP_service; /* Pick a random transaction ID */ bootp->XID = RTCS_rand(); /* Set initial timeout */ bootp->TIMEOUT = BOOTP_TIMEOUT_MIN; bootp->SECS = 0; /* Build a BOOTREQUEST packet */ mqx_htonc(bootp->PACKET.OP, BOOTPOP_BOOTREQUEST); mqx_htonc(bootp->PACKET.HTYPE, if_ptr->DEV_TYPE); mqx_htonc(bootp->PACKET.HLEN, if_ptr->DEV_ADDRLEN); mqx_htonc(bootp->PACKET.HOPS, 0); mqx_htonl(bootp->PACKET.XID, bootp->XID); mqx_htons(bootp->PACKET.FLAGS, 0x8000); mqx_htonl(bootp->PACKET.CIADDR, INADDR_ANY); mqx_htonl(bootp->PACKET.YIADDR, INADDR_ANY); mqx_htonl(bootp->PACKET.SIADDR, INADDR_ANY); mqx_htonl(bootp->PACKET.GIADDR, INADDR_ANY); _mem_zero(bootp->PACKET.CHADDR, sizeof(bootp->PACKET.CHADDR)); _mem_copy(if_ptr->DEV_ADDR, bootp->PACKET.CHADDR, if_ptr->DEV_ADDRLEN); /* Start the retransmission timer to start sending immediately */ bootp->RESEND.TIME = 0; bootp->RESEND.EVENT = BOOTP_send; bootp->RESEND.PRIVATE = if_ptr; TCPIP_Event_add(&bootp->RESEND); if_ptr->BOOT = (void *)parms; } /* Endbody */
bool DHCP_option_addrlist ( unsigned char * *optptr, uint32_t *optlen, unsigned char opttype, _ip_address *addrptr, uint32_t addrcount ) { /* Body */ unsigned char *opt = *optptr; _ip_address addr; if ((*optlen) < 4*addrcount+2) return FALSE; mqx_htonc(opt, opttype); opt++; mqx_htonc(opt, 4*addrcount); opt++; while (addrcount--) { addr = *addrptr++; mqx_htonl(opt, addr); opt += 4; } /* Endwhile */ *optlen -= 4*addrcount+2; *optptr = opt; return TRUE; } /* Endbody */
static void RIP_build_rte( unsigned char *buf, /* [OUT] the route entry */ uint16_t family, uint16_t rt_tag, _ip_address net_addr, _ip_address net_mask, _ip_address next_hop, uint32_t metric, uint32_t rip_vers ) { /* Body */ RIP_ENTRY_PTR rte = (RIP_ENTRY_PTR)buf; if (rip_vers == RIP_V2){ mqx_htons(rte->RT_TAG, rt_tag); mqx_htonl(rte->NETMASK, net_mask); mqx_htonl(rte->NEXTHOP, next_hop); }else{ _mem_zero(buf, sizeof(RIP_ENTRY)); } mqx_htons(rte->FAMILY, family); mqx_htonl(rte->NETADDR, net_addr); mqx_htonl(rte->METRIC, metric); } /* Endbody */
bool DHCP_option_addr ( unsigned char * *optptr, uint32_t *optlen, unsigned char opttype, _ip_address addr ) { /* Body */ unsigned char *opt = *optptr; if ((*optlen) < 6) return FALSE; mqx_htonc(opt, opttype); opt++; mqx_htonc(opt, 4); opt++; mqx_htonl(opt, addr); opt += 4; *optlen -= 6; *optptr = opt; return TRUE; } /* Endbody */
bool IGMP_send_report ( ip_mreq *igrp, uint16_t type ) { /* Body */ IGMP_CFG_STRUCT_PTR IGMP_cfg_ptr = RTCS_getcfg(IGMP); uint32_t error; uint16_t checksum; RTCSPCB_PTR pcb; IGMP_HEADER_PTR header; IP_IF_PTR ipif; _ip_address ipdst; IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.COMMON.ST_TX_TOTAL++); /* never send a report for the local groups */ if (IN_LOCAL_MULTICAST(igrp->imr_multiaddr.s_addr)) { return TRUE; } /* Endif */ /* get the interface with its ip address */ ipif = IP_find_if(igrp->imr_interface.s_addr); if (ipif == NULL) { IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.COMMON.ST_TX_MISSED++); return FALSE; } /* Endif */ pcb = RTCSPCB_alloc_send(); if (pcb == NULL) { IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.COMMON.ST_TX_MISSED++); return FALSE; } /* Endif */ //RTCSLOG_PCB_ALLOC(pcb); error = RTCSPCB_insert_header(pcb, sizeof(IGMP_HEADER)); if (error) { RTCSLOG_PCB_FREE(pcb, error); RTCSPCB_free(pcb); IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.COMMON.ST_TX_MISSED++); return FALSE; } /* Endif */ RTCSLOG_PCB_WRITE(pcb, RTCS_LOGCTRL_PROTO(IPPROTO_IGMP), 1); #ifdef IGMP_V2 /* check if routers igmpv1 are present or not */ if (type == IGMPTYPE_V2_REPORT && ipif->IGMP_V1_ROUTER_FLAG) { uint32_t curTime = RTCS_time_get(); /* WORK: handle the overflow (see tcp seq) */ if (curTime < ipif->IGMP_V1_ROUTER_TIMEOUT) { type = IGMPTYPE_V1_REPORT; } else { /* if the timeout expired, clear the flag */ ipif->IGMP_V1_ROUTER_FLAG = 0; } /* Endif */ } /* Endif */ #endif /* IGMP_V2 */ /* build the igmp packet */ header = (IGMP_HEADER_PTR)RTCSPCB_DATA(pcb); mqx_htonc(header->TYPE, type); mqx_htonc(header->MAX_RESP_TIME, 0); mqx_htons(header->CHECKSUM, 0); mqx_htonl(header->GROUP_ADDRESS, igrp->imr_multiaddr.s_addr); checksum = _mem_sum_ip(0, sizeof(IGMP_HEADER), header); checksum = IP_Sum_invert(checksum); mqx_htons(header->CHECKSUM, checksum); /* WORK: for IGMP_V2, add a router alert option but currently ip layer doesnt support ip options */ /* send the igmp packet */ ipdst = igrp->imr_multiaddr.s_addr; #ifdef IGMP_V2 if (type == IGMPTYPE_LEAVE) { ipdst = INADDR_ALLROUTERS_GROUP; } /* Endif */ #endif IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.ST_TX_REPORT++); /* WORK: not always true for IGMP_V2 */ error = IP_send(pcb, IPPROTO_IGMP | IPTTL(1), igrp->imr_interface.s_addr, ipdst, RTCS_MSG_NOLOOP); return TRUE; } /* Endbody */
void ICMP_send_error_internal ( uint8_t type, /* [IN] the type to send */ uint8_t code, /* [IN] the code to send */ uint32_t param, /* [IN] a parameter */ IP_HEADER_PTR iph, /* [IN] the IP header */ RTCSPCB_PTR origpcb, /* [IN] pcb with bad packet */ uint32_t maxlen /* [IN] the max data len to send, 0 = default */ ) { /* Body */ ICMP_CFG_STRUCT_PTR ICMP_cfg_ptr = RTCS_getcfg(ICMP); RTCSPCB_PTR pcb; ICMP_ERR_HEADER_PTR icmph; _ip_address ipsrc = mqx_ntohl(iph->SOURCE); _ip_address ipdst = mqx_ntohl(iph->DEST); uint16_t iphdrlen = (mqx_ntohc(iph->VERSLEN) & 0x0F) << 2; uint16_t ippktlen = mqx_ntohs(iph->LENGTH) - iphdrlen; uint16_t checksum; _ip_address icmpsrc = IP_is_local(NULL,ipdst) ? ipdst : INADDR_ANY; uint32_t error; unsigned char *buffer; uint32_t temp; #if RTCSCFG_ENABLE_NAT TCP_HEADER_PTR tcp_hdr; UDP_HEADER_PTR udp_hdr; IP_HEADER_PTR ip_hdr; uint32_t protocol; uint16_t src_port, dest_port; uint32_t (_CODE_PTR_ *nat_exec)(RTCSPCB_PTR *); #endif #if BSPCFG_ENET_HW_TX_PROTOCOL_CHECKSUM _ip_address if_addr; IP_IF_PTR if_ptr; #endif /* ** Only include up to a maximum of maxlen bytes of data from the ** original IP datagram */ if (!maxlen) { maxlen = IP_DEFAULT_MTU - sizeof(IP_HEADER) - sizeof(ICMP_HEADER) - 4; } /* Endif */ if (origpcb) { temp = RTCSPCB_DATA(origpcb) - RTCSPCB_DATA_NETWORK(origpcb); if (maxlen > origpcb->HEADER_FRAG_USED + temp) { maxlen = origpcb->HEADER_FRAG_USED + temp; } /* Endif */ } /* Endif */ if (ippktlen + iphdrlen > maxlen) { ippktlen = maxlen - iphdrlen; } /* Endif */ /* Don't send an error in response to an ICMP error */ if (mqx_ntohc(iph->PROTOCOL) == IPPROTO_ICMP) { /* Make sure the packet has at least a 'TYPE' field */ if (ippktlen == 0) { return; } /* Endif */ icmph = (ICMP_ERR_HEADER_PTR)((unsigned char *)iph + iphdrlen); if (!ICMPTYPE_ISQUERY(mqx_ntohc(icmph->HEAD.TYPE))) { return; } /* Endif */ } /* Endif */ IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_TX_TOTAL++); /* Allocate a PCB */ pcb = RTCSPCB_alloc_send(); if (pcb == NULL) { IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_TX_MISSED++); return; } /* Endif */ //RTCSLOG_PCB_ALLOC(pcb); if (origpcb) { /* Add a dependency and a pointer to the ICMP data */ RTCSPCB_depend(pcb, origpcb); error = RTCSPCB_append_fragment(pcb, iphdrlen + ippktlen, (unsigned char *)iph); } else { /* Reserve space for the ICMP data */ buffer = RTCS_mem_alloc_system(iphdrlen + ippktlen); if (!buffer) { IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_TX_MISSED++); IF_ICMP_STATS_ENABLED(RTCS_seterror(&ICMP_cfg_ptr->STATS.ERR_TX, RTCSERR_OUT_OF_MEMORY, (uint32_t)pcb)); RTCSLOG_PCB_FREE(pcb, RTCSERR_OUT_OF_MEMORY); RTCSPCB_free(pcb); return; } /* Endif */ _mem_set_type(buffer, MEM_TYPE_ICMP_DATA); _mem_copy(iph, buffer, iphdrlen + ippktlen); error = RTCSPCB_append_fragment_autofree(pcb, iphdrlen + ippktlen, buffer); if (error) { _mem_free(buffer); } /* Endif */ } /* Endif */ if (!error) { error = RTCSPCB_insert_header(pcb, sizeof(ICMP_HEADER) + 4); } /* Endif */ if (error) { IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_TX_MISSED++); IF_ICMP_STATS_ENABLED(RTCS_seterror(&ICMP_cfg_ptr->STATS.ERR_TX, error, (uint32_t)pcb)); RTCSLOG_PCB_FREE(pcb, error); RTCSPCB_free(pcb); return; } /* Endif */ RTCSLOG_PCB_WRITE(pcb, RTCS_LOGCTRL_PROTO(IPPROTO_ICMP), 0); /* Build the header */ icmph = (ICMP_ERR_HEADER_PTR)RTCSPCB_DATA(pcb); mqx_htonc(icmph->HEAD.TYPE, type); mqx_htonc(icmph->HEAD.CODE, code); mqx_htons(icmph->HEAD.CHECKSUM, 0); mqx_htonl(icmph->DATA, param); #if BSPCFG_ENET_HW_TX_PROTOCOL_CHECKSUM /* HW-offload.*/ if_addr = IP_route_find(ipsrc /* Destination*/, 1); if_ptr = IP_find_if(if_addr); if( (if_ptr && (if_ptr->FEATURES & IP_IF_FEATURE_HW_TX_PROTOCOL_CHECKSUM) && (IP_will_fragment(if_ptr, RTCSPCB_SIZE(pcb)) == FALSE)) #if RTCSCFG_LINKOPT_8023 && (pcb->LINK_OPTIONS.TX.OPT_8023 == 0) #endif ) { pcb->TYPE |= RTCSPCB_TYPE_HW_PROTOCOL_CHECKSUM; } else #endif { checksum = IP_Sum_PCB (0, pcb); checksum = IP_Sum_invert(checksum); mqx_htons(icmph->HEAD.CHECKSUM, checksum); pcb->TYPE &= ~RTCSPCB_TYPE_HW_PROTOCOL_CHECKSUM; } #if RTCSCFG_ENABLE_ICMP_STATS /* Update the statistics */ switch (type) { case ICMPTYPE_DESTUNREACH: ICMP_cfg_ptr->STATS.ST_TX_DESTUNREACH++; break; case ICMPTYPE_TIMEEXCEED: ICMP_cfg_ptr->STATS.ST_TX_TIMEEXCEED++; break; case ICMPTYPE_PARMPROB: ICMP_cfg_ptr->STATS.ST_TX_PARMPROB++; break; case ICMPTYPE_SRCQUENCH: ICMP_cfg_ptr->STATS.ST_TX_SRCQUENCH++; break; case ICMPTYPE_REDIRECT: ICMP_cfg_ptr->STATS.ST_TX_REDIRECT++; break; case ICMPTYPE_ECHO_REQ: ICMP_cfg_ptr->STATS.ST_TX_ECHO_REQ++; break; case ICMPTYPE_ECHO_REPLY: ICMP_cfg_ptr->STATS.ST_TX_ECHO_REPLY++; break; case ICMPTYPE_TIME_REQ: ICMP_cfg_ptr->STATS.ST_TX_TIME_REQ++; break; case ICMPTYPE_TIME_REPLY: ICMP_cfg_ptr->STATS.ST_TX_TIME_REPLY++; break; case ICMPTYPE_INFO_REQ: ICMP_cfg_ptr->STATS.ST_TX_INFO_REQ++; break; case ICMPTYPE_INFO_REPLY: ICMP_cfg_ptr->STATS.ST_TX_INFO_REPLY++; break; default: ICMP_cfg_ptr->STATS.ST_TX_OTHER++; break; } /* Endswitch */ #endif #if RTCSCFG_ENABLE_NAT /* Reverse NAT (if it is installed) on the origpcb, otherwise the icmp error will not get sent to the original src */ nat_exec = RTCS_getcfg(NAT); if (origpcb && nat_exec && *nat_exec) { // swap src and dst IPs and ports so NAT_apply // will process the pcb ip_hdr = (IP_HEADER_PTR)RTCSPCB_DATA(origpcb); protocol = mqx_ntohc(ip_hdr->PROTOCOL); // Swap ports if it is udp or tcp if ((protocol == IPPROTO_TCP) || (protocol == IPPROTO_UDP)) { switch(protocol) { case IPPROTO_TCP: tcp_hdr = (TCP_HEADER_PTR)((unsigned char *)ip_hdr + IPH_LEN(ip_hdr)); dest_port = mqx_ntohs(tcp_hdr->dest_port); src_port = mqx_ntohs(tcp_hdr->source_port); mqx_htons(tcp_hdr->dest_port, src_port); mqx_htons(tcp_hdr->source_port, dest_port); break; case IPPROTO_UDP: udp_hdr = (UDP_HEADER_PTR)((unsigned char *)ip_hdr + IPH_LEN(ip_hdr)); dest_port = mqx_ntohs(udp_hdr->DEST_PORT); src_port = mqx_ntohs(udp_hdr->SRC_PORT); mqx_htons(udp_hdr->DEST_PORT, src_port); mqx_htons(udp_hdr->SRC_PORT, dest_port); break; default: // should not get here break; } } // swap IPs ipsrc = mqx_ntohl(ip_hdr->SOURCE); ipdst = mqx_ntohl(ip_hdr->DEST); mqx_htonl(ip_hdr->SOURCE, ipdst); mqx_htonl(ip_hdr->DEST,ipsrc); // call NAT error = (*nat_exec)(&origpcb); if (!error) { // swap IPs and ports back ip_hdr = (IP_HEADER_PTR)RTCSPCB_DATA(origpcb); protocol = mqx_ntohc(ip_hdr->PROTOCOL); // swap ports if it is udp or tcp if ((protocol == IPPROTO_TCP) || (protocol == IPPROTO_UDP)) { switch(protocol) { case IPPROTO_TCP: tcp_hdr = (TCP_HEADER_PTR)((unsigned char *)ip_hdr + IPH_LEN(ip_hdr)); dest_port = mqx_ntohs(tcp_hdr->dest_port); src_port = mqx_ntohs(tcp_hdr->source_port); mqx_htons(tcp_hdr->dest_port, src_port); mqx_htons(tcp_hdr->source_port, dest_port); break; case IPPROTO_UDP: udp_hdr = (UDP_HEADER_PTR)((unsigned char *)ip_hdr + IPH_LEN(ip_hdr)); dest_port = mqx_ntohs(udp_hdr->DEST_PORT); src_port = mqx_ntohs(udp_hdr->SRC_PORT); mqx_htons(udp_hdr->DEST_PORT, src_port); mqx_htons(udp_hdr->SRC_PORT, dest_port); break; default: // should not get here break; } } // swap IPs ipsrc = mqx_ntohl(ip_hdr->SOURCE); ipdst = mqx_ntohl(ip_hdr->DEST); mqx_htonl(ip_hdr->SOURCE, ipdst); mqx_htonl(ip_hdr->DEST,ipsrc); // Recalculate the cksum mqx_htons(icmph->HEAD.CHECKSUM, 0); checksum = IP_Sum_PCB (0, pcb); checksum = IP_Sum_invert(checksum); mqx_htons(icmph->HEAD.CHECKSUM, checksum); // recalculate icmpsrc, and use new ipsrc. ipdst = mqx_ntohl(ip_hdr->DEST); ipsrc = mqx_ntohl(ip_hdr->SOURCE); icmpsrc = IP_is_local(NULL,ipdst) ? ipdst : INADDR_ANY; } } #endif /* Send it */ IP_send(pcb, IPPROTO_ICMP, icmpsrc, ipsrc, 0); } /* Endbody */
static uint32_t LCP_recvconfreq ( PPPFSM_CFG_PTR fsm, /* [IN] - State Machine */ bool reject /* [IN] - whether to ConfRej if we disagree */ ) { /* Body */ LCP_CFG_PTR lcp_ptr = fsm->PRIVATE; unsigned char *inp = fsm->DATA; unsigned char *nakp, *rejp; uint32_t sizeleft = fsm->LENGTH; uint32_t naklen, rejlen; bool apneg = FALSE; PPP_OPT req_opt = lcp_ptr->SEND_OPT; unsigned char code; unsigned char cicode, cilen; /* Start CR 2207 */ #if PPP_SECRETS_NOT_SHARED PPP_CFG_PTR ppp_ptr = lcp_ptr->HANDLE; #endif /* End CR 2207 */ #define CI_REJECT(n) \ inp -= n; \ code = CP_CODE_CONF_REJ; \ rejlen += cilen; \ while (cilen--) *rejp++ = *inp++ #define CI_NAK \ if (code != CP_CODE_CONF_REJ) { \ code = CP_CODE_CONF_NAK; \ if (reject) { \ inp -= cilen; \ naklen += cilen; \ while (cilen--) *nakp++ = *inp++; \ } else { \ apneg = FALSE; #define CI_ENDNAK \ } /* Endif */ \ } /* Endif */ #define CI_NAKAP(n) \ if (code != CP_CODE_CONF_REJ) { \ code = CP_CODE_CONF_NAK; \ if (reject) { \ inp -= n; \ naklen += cilen; \ while (cilen--) *nakp++ = *inp++; \ } else { \ apneg = TRUE; \ inp += cilen - n; \ } /* Endif */ \ } else { \ inp += cilen - n; \ } /* Endif */ /* ** Process all requested codes */ rejp = nakp = inp; rejlen = naklen = 0; code = CP_CODE_CONF_ACK; while (sizeleft) { /* check remaining length */ if (sizeleft < inp[1] || inp[1] < 2) { code = CP_CODE_CONF_REJ; rejlen += sizeleft; while (sizeleft--) *rejp++ = *inp++; break; } /* Endif */ cicode = *inp++; sizeleft -= cilen = *inp++; switch (cicode) { case LCP_CI_MRU: if (cilen != 4) { CI_REJECT(2); break; } /* Endif */ /* Accept any MRU no smaller than 68 bytes */ req_opt.MRU = mqx_ntohs(inp); inp += 2; if (req_opt.MRU > DEFAULT_MRU) { req_opt.MRU = DEFAULT_MRU; } else if (req_opt.MRU < MINIMUM_MRU) { CI_NAK { *nakp++ = LCP_CI_MRU; naklen += *nakp++ = 4; req_opt.MRU = MINIMUM_MRU; mqx_htons(nakp, req_opt.MRU); nakp += 2; } CI_ENDNAK; } /* Endif */ break; case LCP_CI_ACCM: if (cilen != 6) { CI_REJECT(2); break; } /* Endif */ /* If we want any characters not in their ACCM, nak it */ req_opt.ACCM = mqx_ntohl(inp); inp += 4; if ((req_opt.ACCM & _PPP_ACCM) != _PPP_ACCM) { CI_NAK { *nakp++ = LCP_CI_ACCM; naklen += *nakp++ = 6; req_opt.ACCM |= _PPP_ACCM; mqx_htonl(nakp, req_opt.ACCM); nakp += 4; } CI_ENDNAK; } /* Endif */ break; /* ** AP is unusual in that it is a variable length ** option. Thus it is possible that we may want ** to nak AP and make a suggestion longer than ** the peer's request. ** ** This is bad. ** ** It's bad because this function wants to reuse ** the incoming ConfReq to build the reply, and ** in this case, it is possible for nakp to ** overtake inp, thus overwriting an option not ** yet parsed. ** ** So we do the following: If we decide to nak ** the requested AP, we just set apneg=TRUE and ** append the nak'd AP at the end of our ConfNak ** after we've completed parsing the ConfReq. ** ** Note that we won't nak AP if we generate ** nak's for other options afterward, because ** the RFC states that nak'd options MUST be in ** the same order that they were in the ConfReq. */ case LCP_CI_AP: if (cilen < 4) { CI_REJECT(2); break; } /* Endif */ /* If we don't have any secrets, reject AP */ /* Start CR 2207 */ if (!(PPP_SECRET(ppp_ptr,_PPP_PAP_LSECRET) || PPP_SECRET(ppp_ptr,_PPP_CHAP_LSECRETS))) { /* End CR 2207 */ CI_REJECT(2); break; } /* Endif */ /* Check the desired authentication protocol */ req_opt.AP = mqx_ntohs(inp); inp += 2; switch (req_opt.AP) { /* Accept PAP only if we have a secret */ case PPP_PROT_PAP: if (cilen != 4) { CI_REJECT(4); break; /* Start CR 2207 */ } else if (PPP_SECRET(ppp_ptr,_PPP_PAP_LSECRET) == NULL) { /* End CR 2207 */ CI_NAKAP(4); break; } /* Endif */ req_opt.AP_Start = PAP_send; break; /* Accept CHAP only if we have a secrets table */ case PPP_PROT_CHAP: if (cilen != 5) { CI_REJECT(4); break; /* Start CR 2207 */ } else if (PPP_SECRET(ppp_ptr,_PPP_CHAP_LSECRETS) == NULL) { /* End CR 2207 */ CI_NAKAP(4); break; } else if (*inp++ != 5) { /* Only MD5 supported */ CI_NAKAP(5); break; } /* Endif */ req_opt.AP_Start = CHAP_open; break; default: CI_NAKAP(4); break; } /* Endswitch */ break; case LCP_CI_MAGIC: if (cilen != 6) { CI_REJECT(2); break; } /* Endif */ inp += 4; break; case LCP_CI_PFC: if (cilen != 2) { CI_REJECT(2); break; } /* Endif */ req_opt.PFC = TRUE; break; case LCP_CI_ACFC: if (cilen != 2) { CI_REJECT(2); break; } /* Endif */ req_opt.ACFC = TRUE; break; default: CI_REJECT(2); break; } /* Endswitch */
static uint32_t LCP_buildconfreq ( PPPFSM_CFG_PTR fsm, /* [IN] - State Machine */ unsigned char *outp, /* [IN] - free packet */ uint32_t sizeleft /* [IN] - size of packet */ ) { /* Body */ LCP_CFG_PTR lcp_ptr = fsm->PRIVATE; uint32_t totlen = 0; uint32_t aplen; #define LCP_BREQ(ci,len) \ *outp++ = LCP_CI_ ## ci; \ *outp++ = len; \ totlen += len /* ** Generate configuration information for each option ** we want to negotiate. */ if (lcp_ptr->RECV_NEG.NEG_MRU) { if (sizeleft >= totlen+4) { LCP_BREQ(MRU,4); mqx_htons(outp, lcp_ptr->RECV_NEG.MRU); outp += 2; } /* Endif */ } /* Endif */ if (lcp_ptr->RECV_NEG.NEG_ACCM) { if (sizeleft >= totlen+6) { LCP_BREQ(ACCM,6); mqx_htonl(outp, lcp_ptr->RECV_NEG.ACCM); outp += 4; } /* Endif */ } /* Endif */ if (lcp_ptr->RECV_NEG.NEG_AP) { switch (lcp_ptr->RECV_NEG.AP) { case PPP_PROT_CHAP: aplen = 5; break; default: aplen = 4; break; } /* Endswitch */ if (sizeleft >= totlen+aplen) { LCP_BREQ(AP,aplen); mqx_htons(outp, lcp_ptr->RECV_NEG.AP); outp += 2; switch (lcp_ptr->RECV_NEG.AP) { case PPP_PROT_CHAP: mqx_htonc(outp, 5); outp++; /* Only MD5 supported */ break; } /* Endswitch */ } /* Endif */ } /* Endif */ if (lcp_ptr->RECV_NEG.NEG_PFC) { if (sizeleft >= totlen+2) { LCP_BREQ(PFC,2); } /* Endif */ } /* Endif */ if (lcp_ptr->RECV_NEG.NEG_ACFC) { if (sizeleft >= totlen+2) { LCP_BREQ(ACFC,2); } /* Endif */ } /* Endif */ return totlen; } /* 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 */