示例#1
0
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 */
示例#2
0
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 */
示例#3
0
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 */
示例#4
0
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 */
示例#5
0
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 */
示例#6
0
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 */
示例#7
0
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 */
示例#8
0
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 */
示例#9
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 */