Exemplo n.º 1
0
static void IPREASM_add_frag
   (
      IP_DGRAM_PTR   dgram,   /* [IN] the dgram */
      RTCSPCB_PTR    inpcb    /* [IN] the received PCB */
   )
{ /* Body */
   IP_HEADER_PTR     iph     = (IP_HEADER_PTR)RTCSPCB_DATA(inpcb);
   uint32_t           iphlen  = (mqx_ntohc(iph->VERSLEN) & 0xF) << 2;
   uint32_t           totlen  = mqx_ntohs(iph->LENGTH);
   int32_t            offset  = mqx_ntohs(iph->FRAGMENT);
   int32_t            first   = (offset & IP_FRAG_MASK) << IP_FRAG_SHIFT;
   uint32_t           datalen = totlen - iphlen;
   unsigned char         *data    = (unsigned char *)iph + iphlen;
   IPREASM_BLK_PTR   blk;
   uint32_t           len;

   if (offset & IP_FRAG_MF) {

      /* Fragments (except the last) must be multiples of 8 bytes */
      if ((datalen & 0x07) != 0) {
         return;
      } /* Endif */

   } else {
      /* If this fragment is the last one, record the total length */
      dgram->TOTLEN = first + datalen;

   } /* Endif */

   /* Once we get the first fragment, record the IP header and 8 data bytes */
   if (first == 0) {
      _mem_copy(iph, &dgram->header.IP4.IPH, iphlen + 8);
      dgram->TYPE    = inpcb->TYPE;
      dgram->IFSRC   = inpcb->IFSRC;
      dgram->LINKOPT = inpcb->LINK_OPTIONS.RX;
   } /* Endif */

   while (datalen) {
      blk = IPREASM_blk_get(dgram, first);
      if (!blk) {
         return;
      } /* Endif */

      len = IPREASM_blk_write(dgram, blk, first, data, datalen);
      first   += len;
      data    += len;
      datalen -= len;
   } /* Endwhile */

} /* Endbody */
Exemplo n.º 2
0
void NAT_ALG_TCP_checksum
   (
      IP_HEADER_PTR    ip_header_ptr    /* [IN]  pointer to IP header */
   )
{ /* Body */
   TRANSPORT_UNION    transport;
   uint16_t           checksum;
   uint16_t           protocol;
   uint16_t           iplen = IPH_LEN(ip_header_ptr);
   uint16_t           len = mqx_ntohs(ip_header_ptr->LENGTH) - iplen; 
   
   /* Get TCP header */
   transport.PTR = TRANSPORT_PTR(ip_header_ptr);

   mqx_htons(transport.TCP_PTR->checksum, 0);    /* Clear checksum field */
   protocol = mqx_ntohc(ip_header_ptr->PROTOCOL); /* PROTOCOL */
   checksum = (uint16_t) _mem_sum_ip(protocol, 8, ip_header_ptr->SOURCE);  /* IP SRC and DST ADDR */
   checksum = (uint16_t) _mem_sum_ip(checksum, len, transport.PTR);

   /* TCP LENGTH */
   checksum = IP_Sum_immediate(checksum, len);
   
   checksum = IP_Sum_invert(checksum);
   mqx_htons(transport.TCP_PTR->checksum, checksum);   

} /* Endbody */
Exemplo n.º 3
0
static unsigned char  *DNS_parse_answer_name_to_dotted_form
   (
   unsigned char  *buffer_ptr,
   unsigned char  *name,
   uint32_t     loc
   )

{  /* Body */

   unsigned char        *compressed_name;
   unsigned char        *fill_ptr;
   unsigned char         label_size;
   uint32_t       i;
   uint16_t       new_location;

   fill_ptr = RTCS_HOST_NAMES[loc];
   _mem_zero(fill_ptr, DNS_MAX_CHARS_IN_NAME);

   compressed_name = name;

   while ( mqx_ntohc(compressed_name) != '\0' ) {

      if ( mqx_ntohc(compressed_name) & DNS_COMPRESSED_NAME_MASK ) {
         new_location = mqx_ntohs(compressed_name)
                        & DNS_COMPRESSED_LOCATION_MASK;
         compressed_name = buffer_ptr + new_location;
      }/* Endif */

      label_size  = mqx_ntohc(compressed_name);
      compressed_name++;

      for ( i = 0; i < label_size; i++ ) {
           *fill_ptr++ = mqx_ntohc(compressed_name);
            compressed_name++;
      } /* Endfor */

      if ( mqx_ntohc(compressed_name) != '\0' ) {
         *fill_ptr++ = '.';
      }/* Endif */
   } /* Endwhile */

   *fill_ptr = '\0';

   return( RTCS_HOST_NAMES[loc] );

}  /* Endbody */
Exemplo n.º 4
0
static void RIP_adopt_rt(
    RTCSPCB_PTR            pcb,          /* [IN] incoming packet */
    IP_ROUTE_INDIRECT_PTR  gate,
    RIP_ENTRY_PTR          rte,
    uint32_t                metric,
    _ip_address       *network_ptr,
    _ip_address       *netmask_ptr
)
{ /* Body */
   RIP_HEADER_PTR  hd = (RIP_HEADER_PTR)RTCSPCB_DATA(pcb);
   uint16_t     rip_vers = mqx_ntohc(hd->VERSION);
   _ip_address ipsrc = IP_source(pcb);

   /* init the common part */
   *network_ptr = mqx_ntohl(rte->NETADDR);
   gate->GATEWAY = ipsrc;
   if (rip_vers == RIP_V2){
      _ip_address nexthop = mqx_ntohl(rte->NEXTHOP);
      *netmask_ptr = mqx_ntohl(rte->NETMASK);
      /* incoming nexthop. rfc2453.4.4 */
      if (nexthop && IP_is_direct(pcb->IFSRC, nexthop))
         gate->GATEWAY = nexthop;
   }else{
      *netmask_ptr = IN_DEFAULT_NET(*network_ptr);
   }

   /* if the metric is >= than the RIP_MAX_METRIC, the ourte is down */
   if (metric < RIP_MAX_METRIC) {
      gate->FLAGS |= RTF_UP;
   } else {
      gate->FLAGS &= ~RTF_UP;
   } /* Endif */

   /* init the RIP part */
   gate->RIP.METRIC = metric;
   gate->RIP.RT_TAG = mqx_ntohs(rte->RT_TAG);

   gate->RIP.CHANGED_F = TRUE;

   gate->RIP.IPIFSRC = pcb->IFSRC;

   RIP_init_timer(gate, gate->RIP.METRIC);
} /* Endbody */
Exemplo n.º 5
0
uint32_t IP_reasm
   (
      RTCSPCB_PTR       pcb,     /* [IN] the packet to deliver */
      RTCSPCB_PTR  *outpcb   /* [OUT] the reassembled packet or NULL */
   )
{ /* Body */
   IP_HEADER_PTR  iph    = (IP_HEADER_PTR)RTCSPCB_DATA(pcb);
   _ip_address    ipsrc  = mqx_ntohl(iph->SOURCE);
   _ip_address    ipdst  = mqx_ntohl(iph->DEST);
   uint8_t         proto  = mqx_ntohc(iph->PROTOCOL);
   uint16_t        id     = mqx_ntohs(iph->ID);
   IP_DGRAM_PTR   dgram;

   *outpcb = NULL;

   dgram = IPREASM_get_dgram(ipsrc, ipdst, proto, id);
   if (!dgram) {
      RTCSLOG_PCB_FREE(pcb, RTCSERR_OUT_OF_MEMORY);
      RTCSPCB_free(pcb);
      return RTCSERR_OUT_OF_MEMORY;
   } /* Endif */

   IPREASM_add_frag(dgram, pcb);

   /*
   ** We're done when:
   **    0 < TOTLEN = MAXLEN <= CURLEN
   **
   ** Note: we can get TOTLEN < CURLEN because CURLEN is
   ** always a multiple of eight, but TOTLEN may not be.
   */
   if (dgram->TOTLEN > 0
    && dgram->MAXLEN == dgram->TOTLEN
    && dgram->CURLEN >= dgram->MAXLEN) {
      *outpcb = IPREASM_reasm_dgram(dgram);
   } /* Endif */

   /* Free the old pcb */
   RTCSLOG_PCB_FREE(pcb, RTCS_OK);
   RTCSPCB_free(pcb);

   return RTCS_OK;
} /* Endbody */
Exemplo n.º 6
0
static uint32_t RIP_is_valid_rte(
    RIP_ENTRY_PTR   rte
)
{ /* Body */
    uint32_t metric = mqx_ntohl(rte->METRIC);
    _ip_address netaddr = mqx_ntohl(rte->NETADDR);
    if (mqx_ntohs(rte->FAMILY) != RIP_AF_INET) return 0;
    if (metric > RIP_MAX_METRIC || metric < RIP_MIN_METRIC) return 0;
    if (IN_MULTICAST(netaddr) || IN_EXPERIMENTAL(netaddr)) return 0;
    if (IN_LOOPBACK(netaddr))  return 0;

    {
      _ip_address   nexthop = mqx_ntohl(rte->NEXTHOP);
      
      if (nexthop!= 0) {
         if (IP_is_local(NULL, nexthop)) {
            return 0;
         }
      }
    }

    return 1;
} /* Endbody */
Exemplo n.º 7
0
static uint32_t RIP_process_inreq(
      RTCSPCB_PTR    pcb          /* [IN/OUT] incoming packet */
)
{ /* Body */
   RIP_HEADER_PTR  hd = (RIP_HEADER_PTR)RTCSPCB_DATA(pcb);
   RIP_ENTRY_PTR   rte = (RIP_ENTRY_PTR)((unsigned char *)hd
                   + sizeof(RIP_HEADER));
   uint32_t     pktlen = RTCSPCB_SIZE(pcb);
   uint32_t     err = RTCS_OK;

   /* handle the general query. rfc2453.3.9.1 */
   if (pktlen == sizeof(RIP_ENTRY) + sizeof(RIP_HEADER)
         && mqx_ntohs(rte->FAMILY) == 0
         && mqx_ntohl(rte->METRIC) == RIP_MAX_METRIC){
      _ip_address ipsrc = IP_source(pcb);
      uint16_t     srcport = UDP_source(pcb);
      uint8_t      version = mqx_ntohc(hd->VERSION);
      return RIP_send_resp_ipif (pcb->IFSRC,ipsrc,srcport,version,0);
   }
/* WORK: here handle particular routes request */

   return err;
} /* Endbody */
Exemplo n.º 8
0
void ICMP_service
   (
      RTCSPCB_PTR    pcb,        /* [IN/OUT] incoming packet */
      void          *dummy       /* [IN]     not used        */
   )
{ /* Body */
   ICMP_CFG_STRUCT_PTR  ICMP_cfg_ptr;
   ICMP_HEADER_PTR      packet;
   _ip_address          source, dest;
   uint32_t              error;
   uint16_t              chksum;
   unsigned char                type;

#if BSPCFG_ENET_HW_TX_PROTOCOL_CHECKSUM
    _ip_address         if_addr;
    IP_IF_PTR           if_ptr;
#endif


   ICMP_cfg_ptr = RTCS_getcfg(ICMP);

   IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_RX_TOTAL++);
   packet = (ICMP_HEADER_PTR)RTCSPCB_DATA(pcb);
   source = IP_source(pcb);
   dest   = IP_dest(pcb);
   type = mqx_ntohc(packet->TYPE);

   /*
   ** Make sure that
   **    sizeof(ICMP_HEADER) <= RTCSPCB_SIZE(pcb)
   */
   if (RTCSPCB_SIZE(pcb) < sizeof(ICMP_HEADER)) {
      IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++);
      IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.ST_RX_SMALL_DGRAM++);
      RTCSLOG_PCB_FREE(pcb, RTCSERR_ICMP_BAD_HEADER);
      RTCSPCB_free(pcb);
      return;
   } /* Endif */


#if BSPCFG_ENET_HW_RX_PROTOCOL_CHECKSUM
    /* HW-offload.*/
    if( ((pcb->TYPE & RTCSPCB_TYPE_HW_PROTOCOL_CHECKSUM)==0) 
    #if RTCSCFG_LINKOPT_8023
        ||(pcb->LINK_OPTIONS.RX.OPT_8023 == 1)
    #endif
      )
#endif
    {
        /* Verify the checksum */
        if (IP_Sum_PCB(0, pcb) != 0xFFFF)
        {
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++);
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.ST_RX_BAD_CHECKSUM++);
            RTCSLOG_PCB_FREE(pcb, RTCSERR_ICMP_BAD_CHECKSUM);
            RTCSPCB_free(pcb);
            return;
        }
    }

   RTCSLOG_PCB_READ(pcb, RTCS_LOGCTRL_PROTO(IPPROTO_ICMP), 0);

   switch (type) {

   case ICMPTYPE_REDIRECT:
#if RTCSCFG_ENABLE_GATEWAYS

      { /* Scope */
         _ip_address          origdest, gateway;
         ICMP_ERR_HEADER_PTR  rdpacket = (ICMP_ERR_HEADER_PTR)packet;
         IPIF_PARM            parms;

         /*
         ** Make sure that
         **    sizeof(ICMP_ERR_HEADER) <= RTCSPCB_SIZE(pcb)
         */
         if (RTCSPCB_SIZE(pcb) < sizeof(ICMP_ERR_HEADER)) {
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++);
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.ST_RX_SMALL_DGRAM++);
            RTCSLOG_PCB_FREE(pcb, RTCSERR_ICMP_BAD_HEADER);
            RTCSPCB_free(pcb);
            return;
         } /* Endif */

         gateway  = mqx_ntohl(rdpacket->DATA);
         origdest = mqx_ntohl(rdpacket->IP.DEST);

        /* If we receive a redirect to ourselves, silently discard it.*/
        /* Ignore unasigned address.*/
        if( IP_is_local(NULL, gateway) || (gateway == INADDR_ANY))
        {
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++);
        }
        else  if(IP_is_gate(source, origdest))
        {
            parms.address = gateway;
            parms.network = origdest;
            parms.netmask = 0xFFFFFFFFL;
            parms.locmask = 0;
            RTCSCMD_internal(parms, IPIF_gate_add_redirect);
        }
        else
        {
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++);
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.ST_RX_RD_NOTGATE++);
        } /* Endif */
        
    } /* Endscope */
#else
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++);
#endif
      break;

    case ICMPTYPE_ECHO_REQ:
        /* RFC1122: An ICMP Echo Request destined to an IP broadcast or IP
         * multicast address MAY be silently discarded.*/
        if((dest == INADDR_BROADCAST) || (IN_MULTICAST(dest) && (ip_if_is_joined(pcb->IFSRC, dest) == false)) )
        {
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++);
        }
        else
        {
            error = RTCSPCB_next(pcb, sizeof(ICMP_HEADER));
            if (error) {
                IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_RX_ERRORS++);
                IF_ICMP_STATS_ENABLED(RTCS_seterror(&ICMP_cfg_ptr->STATS.ERR_RX, error, (uint32_t)pcb));
                RTCSLOG_PCB_FREE(pcb, error);
                RTCSPCB_free(pcb);
                return;
            } /* Endif */

            /*
            ** RTCSPCB_fork() failing isn't a serious error, so we don't check
            ** the error code
            */
            RTCSPCB_fork(pcb);

            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_TX_TOTAL++);
            RTCSLOG_PCB_WRITE(pcb, RTCS_LOGCTRL_PROTO(IPPROTO_ICMP), 0);

            error = RTCSPCB_insert_header(pcb, sizeof(ICMP_HEADER));
            if (error) {
                IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.ST_RX_ECHO_REQ++);
                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;
            }

            /* Change type from Echo to Echo Reply and recalculate checksum */
            packet = (ICMP_HEADER_PTR)RTCSPCB_DATA(pcb);
            mqx_htonc(packet->TYPE, ICMPTYPE_ECHO_REPLY);
            mqx_htonc(packet->CODE, 0);
            mqx_htons(packet->CHECKSUM, 0);
            pcb->IP_SUM_PTR = NULL;


    #if BSPCFG_ENET_HW_TX_PROTOCOL_CHECKSUM
            /* HW-offload.*/
            if_addr = IP_route_find(source /* 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
            {
                chksum = IP_Sum_PCB(0, pcb);
                chksum = IP_Sum_invert(chksum);
                mqx_htons(packet->CHECKSUM, chksum);
                
                pcb->TYPE &= ~RTCSPCB_TYPE_HW_PROTOCOL_CHECKSUM;
            }

            if(IN_MULTICAST(dest) || IP_addr_is_broadcast(pcb, dest) )
            {
                dest = IP_get_ipif_addr(pcb->IFSRC);
            }

            /* Send the Echo Reply whence came the Echo */
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.ST_TX_ECHO_REPLY++);
            IP_send(pcb, IPPROTO_ICMP, dest /* Source*/, source /* Destination*/, 0);
            pcb = NULL;
        }
        break;

   case ICMPTYPE_ECHO_REPLY:
      { /* Scope */
         ICMP_ECHO_HEADER_PTR echopacket = (ICMP_ECHO_HEADER_PTR)packet;
         ICMP_ECHO_PARAM_PTR        parms;
         uint16_t              id, seq;

         /*
         ** Make sure that
         **    sizeof(ICMP_ECHO_HEADER) <= RTCSPCB_SIZE(pcb)
         */
         if (RTCSPCB_SIZE(pcb) < sizeof(ICMP_ECHO_HEADER)) {
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++);
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.ST_RX_SMALL_DGRAM++);
            RTCSLOG_PCB_FREE(pcb, RTCSERR_ICMP_BAD_HEADER);
            RTCSPCB_free(pcb);
            return;
         } /* Endif */

         /*
         ** get the ID and Sequence number from the packet
         */
         id  = mqx_ntohs(echopacket->ID);
         seq = mqx_ntohs(echopacket->SEQ);

         /*
         ** Find a match for the ID and sequence number
         */
         for (parms=ICMP_cfg_ptr->ECHO_PARAM_HEAD; parms; parms=parms->NEXT) {

            if ((parms->ping_param->id == id) && (parms->seq == seq)) {
               /*  received reply for the ping request */

               if (parms->NEXT) {
                  parms->NEXT->PREV = parms->PREV;
               }
               *parms->PREV = parms->NEXT;

               TCPIP_Event_cancel(&parms->EXPIRE);

               /* Calculate round trip time */
               parms->ping_param->round_trip_time = RTCS_timer_get_interval(parms->start_time, RTCS_time_get());
               
                /* IP address of echo-reply message.*/
                {
                    IP_HEADER_PTR iphead = (IP_HEADER_PTR)RTCSPCB_DATA_NETWORK(pcb);
                   
                    memset(&parms->ping_param->addr, 0, sizeof(parms->ping_param->addr));
                    parms->ping_param->addr.sa_family = AF_INET;
                    ((sockaddr_in*)(&parms->ping_param->addr))->sin_addr.s_addr = mqx_ntohl(iphead->SOURCE);
                }

               RTCSCMD_complete(parms, RTCS_OK);
               break;
            } /* Endif */
         } /* Endfor */
      } /* Endscope */
      break;

   case ICMPTYPE_DESTUNREACH:
   case ICMPTYPE_TIMEEXCEED:
      { /* Scope */
         IP_HEADER_PTR       ip;
         ICMP_ERR_HEADER_PTR icmp_err = (ICMP_ERR_HEADER_PTR)packet;
         uint32_t             len, remain;
         bool             discard = TRUE;
         unsigned char               code;

         /*
         ** Check if the attached IP header is IP over IP, and if so, strip IP
         ** headers until we find one whose source address is not local. Then we
         ** forward the ICMP error to that IP address
         */

         remain = RTCSPCB_SIZE(pcb);

         /* Make sure we have at least a full IP header */
         if (remain >= sizeof(ICMP_HEADER) + 4 + sizeof(IP_HEADER)) {
            ip = (IP_HEADER_PTR)((unsigned char *)packet + sizeof(ICMP_HEADER) + 4);
            remain -= sizeof(ICMP_HEADER) + 4;

            do {
               /* Make sure the IP header is IP over IP */
               if (mqx_ntohc(ip->PROTOCOL) != IPPROTO_IPIP) {
                  break;
               } /* Endif */

               /* Make sure we have a full IP header + 8 bytes */
               len = (mqx_ntohc(ip->VERSLEN) & 0x0F) << 2;
               if (remain < len + sizeof(IP_HEADER)) {
                  break;
               } /* Endif */

               /* Get next header */
               ip = (IP_HEADER_PTR)((unsigned char *)(ip) + len);
               remain -= len;
               source = mqx_ntohl(ip->SOURCE);

               discard = IP_is_local(NULL, source);

            } while(discard);

            len = (mqx_ntohc(ip->VERSLEN) & 0x0F) << 2;

            /*
            ** discard is true if we are the originator of the IP packet
            ** in error, or if there was not enough information to find the
            ** originator. We make sure discard is false, and there is at
            ** least a full IP header + 8 bytes of data left
            */
            if (!discard && (len + 8 <= remain)) {
               if (type == ICMPTYPE_DESTUNREACH) {
                  code = mqx_ntohc(packet->CODE);
                  switch (code) {
                  case ICMPCODE_DU_PROTO_UNREACH:
                     /*
                     ** If we are sending back to the originator, and the
                     ** originator did not use IP over IP, the protocol
                     ** unreachable error is useless.
                     */
                     code = ICMPCODE_DU_NET_UNREACH;
                     break;
                  case ICMPCODE_DU_PORT_UNREACH:
                     /* It doesn't make sense to receive this */
                     discard = TRUE;
                     break;
                  case ICMPCODE_DU_SRCROUTE:
                     discard = TRUE;
                     break;
                  } /* Endswitch */
               } else {
                  /*
                  ** Type is ICMPTYPE_TIMEEXCEED
                  **
                  ** Problem with routing loops within tunnel. Originator
                  ** does not need to know about tunnel.
                  */
                  type = ICMPTYPE_DESTUNREACH;
                  code = ICMPCODE_DU_HOST_UNREACH;
               } /* Endif */

               if (!discard) {
                  ICMP_send_error_internal(type, code, mqx_ntohl(icmp_err->DATA),
                     ip, NULL, remain);
               } /* Endif */
            } /* Endif */
         } /* Endif */
      } /* Endscope */
      break;
   } /* End Switch */

#if RTCSCFG_ENABLE_ICMP_STATS
   /* Update the statistics */
   switch (type) {
   case ICMPTYPE_DESTUNREACH: ICMP_cfg_ptr->STATS.ST_RX_DESTUNREACH++; break;
   case ICMPTYPE_TIMEEXCEED:  ICMP_cfg_ptr->STATS.ST_RX_TIMEEXCEED++;  break;
   case ICMPTYPE_PARMPROB:    ICMP_cfg_ptr->STATS.ST_RX_PARMPROB++;    break;
   case ICMPTYPE_SRCQUENCH:   ICMP_cfg_ptr->STATS.ST_RX_SRCQUENCH++;   break;
   case ICMPTYPE_REDIRECT:    ICMP_cfg_ptr->STATS.ST_RX_REDIRECT++;    break;
   case ICMPTYPE_ECHO_REQ:    ICMP_cfg_ptr->STATS.ST_RX_ECHO_REQ++;    break;
   case ICMPTYPE_ECHO_REPLY:  ICMP_cfg_ptr->STATS.ST_RX_ECHO_REPLY++;  break;
   case ICMPTYPE_TIME_REQ:    ICMP_cfg_ptr->STATS.ST_RX_TIME_REQ++;    break;
   case ICMPTYPE_TIME_REPLY:  ICMP_cfg_ptr->STATS.ST_RX_TIME_REPLY++;  break;
   case ICMPTYPE_INFO_REQ:    ICMP_cfg_ptr->STATS.ST_RX_INFO_REQ++;    break;
   case ICMPTYPE_INFO_REPLY:  ICMP_cfg_ptr->STATS.ST_RX_INFO_REPLY++;  break;
   default:                   
      ICMP_cfg_ptr->STATS.ST_RX_OTHER++;       
      ICMP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++;
      break;
   } /* Endswitch */
#endif

   if (pcb) {
      RTCSLOG_PCB_FREE(pcb, RTCS_OK);
      RTCSPCB_free(pcb);
   } /* Endif */

} /* Endbody */
Exemplo n.º 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 */
Exemplo n.º 10
0
void TFTPSRV_service_transaction
   (
      TFTPSRV_STATE_STRUCT_PTR   tftpsrv_ptr,
         /* [IN/OUT] The TFTP Server state */
      TFTP_TRANS_STRUCT_PTR      trans_ptr
         /* [IN/OUT] The transaction state */
   )

{ /* Body */
   sockaddr_in sockaddr_tftp;
   uint32_t     block_num;
   int32_t      pkt_len, write_len;
   uint16_t     sockaddrlen, pkt_op;

   /* receive the datagram */
   sockaddrlen = sizeof(sockaddr_tftp);
   pkt_len = recvfrom(trans_ptr->SOCK, tftpsrv_ptr->BUFFER,
                      TFTP_MAX_MESSAGE_SIZE, 0,(sockaddr *)&sockaddr_tftp, &sockaddrlen);
   if (pkt_len == RTCS_ERROR) {
      return;
   } /* Endif */

   /* verify the sender's address and port */
   if ((trans_ptr->ADDR.sin_port        != sockaddr_tftp.sin_port) ||
       (trans_ptr->ADDR.sin_addr.s_addr != sockaddr_tftp.sin_addr.s_addr)) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_tid, sockaddr_tftp);
      return;
   } /* Endif */

   /* get op and block number */
   if (pkt_len < sizeof(TFTP_HEADER)) {
      TFTP_SEND(trans_ptr->SOCK, _tftp_error_tid, sockaddr_tftp);
      return;
   } /* Endif */
   pkt_op    = mqx_ntohs(tftpsrv_ptr->BUFFER);
   block_num = mqx_ntohs(tftpsrv_ptr->BUFFER + 2);

   /* verify the requested operation */
   if (pkt_op != trans_ptr->RECV_OP) {
      if (pkt_op != TFTPOP_ERROR) {
         TFTP_SEND(trans_ptr->SOCK, _tftp_error_op, sockaddr_tftp);
      } /* Endif */
      TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
      return;
   } /* Endif */

   switch (pkt_op) {
   case TFTPOP_DATA:
      /* We are servicing a write request from a TFTP Client here */
      if (block_num == trans_ptr->BLOCK) {

         pkt_len -= sizeof(TFTP_HEADER);
         write_len = RTCS_io_write(trans_ptr->TRANS_FILE_PTR,
                                   tftpsrv_ptr->BUFFER + sizeof(TFTP_HEADER),
                                   pkt_len);
         fflush(trans_ptr->TRANS_FILE_PTR);
         if (write_len != pkt_len) {
            TFTP_SEND(trans_ptr->SOCK, _tftp_error_srv, trans_ptr->ADDR);
            TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
            return;
         } /* Endif */

         TFTPSRV_build_ACK(trans_ptr);
         trans_ptr->EXIT = (write_len < sizeof(TFTP_PACKET) - sizeof(TFTP_HEADER));
         TFTPSRV_timer_cancel(tftpsrv_ptr, trans_ptr);
         TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, TFTP_timeout_update(&trans_ptr->XMIT_TIMER));
         TFTPSRV_send(trans_ptr);

      } else if (block_num == trans_ptr->BLOCK - 1) {
         TFTPSRV_timer_cancel(tftpsrv_ptr, trans_ptr);
         TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, TFTP_timeout_restart(&trans_ptr->XMIT_TIMER));
         TFTPSRV_send(trans_ptr);
      } /* Endif */
      break;

   case TFTPOP_ACK:
      /* We are servicing a read request */
      if (block_num == trans_ptr->BLOCK) {
         if (trans_ptr->EXIT) {
            /* We've received the last ACK, exit */
            TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
            return;
         } /* Endif */
         TFTPSRV_build_DATA(trans_ptr);
         if (trans_ptr->SEND_SIZE < sizeof(TFTP_HEADER)) {
            TFTP_SEND(trans_ptr->SOCK, _tftp_error_srv, sockaddr_tftp);
            TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
            return;
         } /* Endif */
         TFTPSRV_timer_cancel(tftpsrv_ptr, trans_ptr);
         TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, TFTP_timeout_update(&trans_ptr->XMIT_TIMER));
         TFTPSRV_send(trans_ptr);
      } /* Endif */
      break;

   } /* Endswitch */
} /* Endbody */
Exemplo n.º 11
0
void TFTPSRV_service_request
   (
      TFTPSRV_STATE_STRUCT_PTR   tftpsrv_ptr
         /* [IN/OUT] The TFTP Server state */
   )
{ /* Body */
   TFTP_TRANS_STRUCT_PTR   trans_ptr;
   sockaddr_in             sockaddr_t;
   int32_t                  pkt_len, i;
   uint32_t                 error;
   char                *filename, *filemode;
   uint16_t                 sockaddrlen, pkt_op;

   /* receive the datagram */
   sockaddrlen = sizeof(sockaddr_t);
   pkt_len = recvfrom(tftpsrv_ptr->SRV_SOCK, tftpsrv_ptr->BUFFER,
                      TFTP_MAX_MESSAGE_SIZE, 0, (sockaddr *)&sockaddr_t, &sockaddrlen);
   if (pkt_len == RTCS_ERROR) {
      return;
   } /* Endif */

   /* limit the number of concurrent transactions */
   if (tftpsrv_ptr->NUM_TRANSACTIONS >= TFTPSRV_MAX_TRANSACTIONS) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_busy, sockaddr_t);
      return;
   } /* Endif */

   /* parse the request; extract op, filename and filemode */
   i = 2;
   filename = (char *)tftpsrv_ptr->BUFFER + i;
   for (; i<pkt_len; i++) {
      if (tftpsrv_ptr->BUFFER[i] == '\0') break;
   } /* Endfor */
   i++;
   filemode = (char *)tftpsrv_ptr->BUFFER + i;
   for (; i<pkt_len; i++) {
      if (tftpsrv_ptr->BUFFER[i] == '\0') break;
   } /* Endfor */
   if (i >= pkt_len) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_op, sockaddr_t);
      return;
   } /* Endif */
   pkt_op = mqx_ntohs(tftpsrv_ptr->BUFFER);

   /* allocate state for the new transaction */
   trans_ptr = RTCS_mem_alloc_zero(sizeof(TFTP_TRANS_STRUCT));
   if (trans_ptr == NULL) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
      return;
   } /* Endif */
   _mem_set_type(trans_ptr, MEM_TYPE_TFTP_TRANS_STRUCT);
   
   /* validate the requested operation */
   switch (pkt_op) {
   case TFTPOP_RRQ:
      trans_ptr->RECV_OP = TFTPOP_ACK;
      trans_ptr->SEND_OP = TFTPOP_DATA;
      break;
   case TFTPOP_WRQ:
      trans_ptr->RECV_OP = TFTPOP_DATA;
      trans_ptr->SEND_OP = TFTPOP_ACK;
      break;
   default:
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_op, sockaddr_t);
      _mem_free(trans_ptr);
      return;
   } /* Endswitch */

   /* open the requested file */
   error = TFTPSRV_open_device(pkt_op, filename, filemode, &trans_ptr->TRANS_FILE_PTR);
   if (error) {
      switch (error) {
      case RTCS_EACCES:
         TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_accvio, sockaddr_t);
         break;
      case RTCS_ENOENT:
         TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_nofile, sockaddr_t);
         break;
      case RTCS_EEXIST:
         TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_exists, sockaddr_t);
         break;
      default:
         TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
         break;
      } /* Endswitch */
      _mem_free(trans_ptr);
      return;
   } /* Endif */

   /* create a socket for the new transaction */
   trans_ptr->SOCK = socket(PF_INET, SOCK_DGRAM, 0);
   if (trans_ptr->SOCK == RTCS_SOCKET_ERROR) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
      RTCS_io_close(trans_ptr->TRANS_FILE_PTR);
      _mem_free(trans_ptr);
      return;
   } /* Endif */

   trans_ptr->ADDR.sin_family      = sockaddr_t.sin_family;
   trans_ptr->ADDR.sin_port        = sockaddr_t.sin_port;
   trans_ptr->ADDR.sin_addr.s_addr = sockaddr_t.sin_addr.s_addr;

   sockaddr_t.sin_family      = AF_INET;
   sockaddr_t.sin_port        = 0;
   sockaddr_t.sin_addr.s_addr = INADDR_ANY;

   error = bind(trans_ptr->SOCK, (const sockaddr *)&sockaddr_t, sizeof(sockaddr_t));
   if (error != RTCS_OK) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
      shutdown(trans_ptr->SOCK, 0);
      RTCS_io_close(trans_ptr->TRANS_FILE_PTR);
      _mem_free(trans_ptr);
      return;
   } /* Endif */

   /* build the first packet */
   trans_ptr->BLOCK = 0;
   switch (trans_ptr->SEND_OP) {
   case TFTPOP_DATA:
      TFTPSRV_build_DATA(trans_ptr);
      break;
   case TFTPOP_ACK:
      TFTPSRV_build_ACK(trans_ptr);
      trans_ptr->EXIT = FALSE;
      break;
   } /* Endswitch */
   if (trans_ptr->SEND_SIZE < sizeof(TFTP_HEADER)) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
      shutdown(trans_ptr->SOCK, 0);
      RTCS_io_close(trans_ptr->TRANS_FILE_PTR);
      _mem_free(trans_ptr);
      return;
   } /* Endif */

   /* send the first packet */
   TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, TFTP_timeout_init(&trans_ptr->XMIT_TIMER));
   TFTPSRV_send(trans_ptr);

   tftpsrv_ptr->SOCKETS[tftpsrv_ptr->NUM_TRANSACTIONS] = trans_ptr->SOCK;
   tftpsrv_ptr->TRANS_PTRS[tftpsrv_ptr->NUM_TRANSACTIONS] = trans_ptr;
   tftpsrv_ptr->NUM_TRANSACTIONS++;

} /* Endbody */
Exemplo n.º 12
0
static bool LCP_recvconfack
   (
      PPPFSM_CFG_PTR    fsm
            /* [IN] - State Machine */
   )
{ /* Body */
   LCP_CFG_PTR lcp_ptr = fsm->PRIVATE;
   unsigned char   *inp = fsm->DATA;
   uint32_t     sizeleft = fsm->LENGTH;
   uint32_t     aplen;
   PPP_OPT     ack_opt = lcp_ptr->RECV_OPT;

#define LCP_RACK(ci,len) \
      if (sizeleft < len) goto badack;          \
      if (*inp++ != LCP_CI_ ## ci) goto badack; \
      if (*inp++ != len)           goto badack; \
      sizeleft -= len


   /*
   ** The ack must be identical to the last ConfReq we sent
   */
    /*
    ** This situation can happend when size of data in our request packet is "0"
    ** So, size of received data in "ack" packet will be "0" too.
    ** As example: We send "REQ" packet with field PFC an ACFC "ON", modem send "NAK" 
    ** for that field. We turn of that field, but we have not what negotiate else,
    ** so we send "REQ" packed,it looks like "7E FF 03 C0 21 01 6D 00 04 3F 15 7E"
    ** As you see size of data field is "0". But modem agree and send us "ACK" looks like
    ** "7E FF 03 C0 21 02 6D 00 04 F2 30 7E" and will be ready to start next stage of communication.
    ** In received packet from modem you can se size of data field is "0" too.
    */
    if(sizeleft ==0)
    {
        return TRUE; 
    }
    

   if (lcp_ptr->RECV_NEG.NEG_MRU) {
      LCP_RACK(MRU,4);
      ack_opt.MRU = mqx_ntohs(inp); inp += 2;
      if (ack_opt.MRU != lcp_ptr->RECV_NEG.MRU) goto badack;
   } /* Endif */

   if (lcp_ptr->RECV_NEG.NEG_ACCM) {
      LCP_RACK(ACCM,6);
      ack_opt.ACCM = mqx_ntohl(inp); inp += 4;
      if (ack_opt.ACCM != lcp_ptr->RECV_NEG.ACCM) goto badack;
   } /* 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 */
      LCP_RACK(AP,aplen);
      ack_opt.AP = mqx_ntohs(inp); inp += 2;
      if (ack_opt.AP != lcp_ptr->RECV_NEG.AP) goto badack;
      switch (ack_opt.AP) {
      case PPP_PROT_CHAP:
         if (mqx_ntohc(inp) != 5) goto badack;   /* Only MD5 supported */
         inp++;
         ack_opt.AP_Start = CHAP_challenge;
         break;
      case PPP_PROT_PAP:
         ack_opt.AP_Start = PAP_open;
         break;
      default:
         ack_opt.AP = 0;
         break;
      } /* Endswitch */
   } /* Endif */

   if (lcp_ptr->RECV_NEG.NEG_PFC) {
      LCP_RACK(PFC,2);
      ack_opt.PFC = TRUE;
   } /* Endif */

   if (lcp_ptr->RECV_NEG.NEG_ACFC) {
      LCP_RACK(ACFC,2);
      ack_opt.ACFC = TRUE;
   } /* Endif */

   if (sizeleft) goto badack;

   if (fsm->STATE < PPP_STATE_OPENED) {
      lcp_ptr->RECV_OPT = ack_opt;
   } /* Endif */
   return TRUE;

badack:
   return FALSE;

} /* Endbody */
Exemplo n.º 13
0
static bool LCP_recvconfnak
   (
      PPPFSM_CFG_PTR    fsm
            /* [IN] - State Machine */
   )
{ /* Body */
   LCP_CFG_PTR lcp_ptr = fsm->PRIVATE;
   unsigned char   *inp = fsm->DATA;
   uint32_t     sizeleft = fsm->LENGTH;
   LCP_NEG     req_neg = lcp_ptr->RECV_NEG;
   unsigned char       code;
/* Start CR 2207 */
#if PPP_SECRETS_NOT_SHARED
   PPP_CFG_PTR    ppp_ptr = lcp_ptr->HANDLE;
#endif
/* End CR 2207 */

#define LCP_RNAK(len) \
      if (sizeleft < len) goto badnak; \
      if (*inp++ != len)  goto badnak; \
      sizeleft -= len

   /*
   ** Nak'd codes must be in the same order as they were in the ConfReq
   */

   code = *inp++;

   if (sizeleft && req_neg.NEG_MRU && code == LCP_CI_MRU) {
      LCP_RNAK(4);

         /* We are prepared to accept maximum MRU of 1500 */
      req_neg.MRU = mqx_ntohs(inp); inp += 2;
      if (req_neg.MRU > DEFAULT_MRU) {
         req_neg.MRU = DEFAULT_MRU;
      } /* Endif */

      code = *inp++;
   } /* Endif */

   if (sizeleft && req_neg.NEG_ACCM && code == LCP_CI_ACCM) {
      LCP_RNAK(6);

         /* Add any characters they want to our ACCM */
      req_neg.ACCM |= mqx_ntohl(inp); inp += 4;

      code = *inp++;
   } /* Endif */

   if (sizeleft && req_neg.NEG_AP && code == LCP_CI_AP) {
      if (sizeleft < *inp || *inp < 4) goto badnak;
      sizeleft -= *inp;

         /*
         ** If AP is nak'd, we don't care what they want --
         ** we choose the next most desirable protocol.  If there
         ** aren't any more to choose, we keep the last one we tried.
         */
      inp += *inp - 1;
      
      if (PPP_SECRET(ppp_ptr,_PPP_CHAP_RSECRETS)) {
          req_neg.AP = PPP_PROT_CHAP;
      } else {
        switch (req_neg.AP) {
        case PPP_PROT_CHAP:
             /* CHAP was NAKed, try PAP */ 
             if (PPP_SECRET(ppp_ptr,_PPP_PAP_RSECRETS)) {
                req_neg.AP = PPP_PROT_PAP;            
             } /* Endif */
             break;
        
        case PPP_PROT_PAP:
           /* no other authentication protocols known */
           break;
           
        default:
            /* Unknown protocol NAKed, try CHAP */
            if (PPP_SECRET(ppp_ptr,_PPP_CHAP_RSECRETS)) {
                req_neg.AP = PPP_PROT_CHAP;
            }
            break;

        } /* Endswitch */
      }
      code = *inp++;
   } /* Endif */

   /*
   ** If we advertised PFC and/or ACFC and the peer doesn't
   ** want it, they should send a ConfRej rather than a ConfNak,
   ** so we're not going to check for them here (if they are
   ** here, the switch statement below will catch it).
   */


#define LCP_RNAK_ADD(ci,len) \
         if (req_neg.NEG_ ## ci || sizeleft < len || *inp++ != len) goto badnak; \
         sizeleft -= len;                                                        \
         req_neg.NEG_ ## ci = 1

   /*
   ** There may be remaining codes if the peer wants us to
   ** negotiate an option we didn't include.
   */

   while (sizeleft) {
      switch (code) {
      case LCP_CI_MRU:
         LCP_RNAK_ADD(MRU,4);
         req_neg.MRU = mqx_ntohs(inp); inp += 2;
         if (req_neg.MRU > DEFAULT_MRU) {
            req_neg.MRU = DEFAULT_MRU;
         } /* Endif */
         break;
      case LCP_CI_ACCM:
         LCP_RNAK_ADD(ACCM,6);
         req_neg.ACCM |= mqx_ntohl(inp); inp += 4;
         break;
      case LCP_CI_AP:
         if (req_neg.NEG_AP || sizeleft < *inp || *inp < 4) goto badnak;
         sizeleft -= *inp;
            /*
            ** If AP is nak'd, we don't care what they want --
            ** we still don't negotiate
            */
         inp += *inp - 1;
         break;
      case LCP_CI_PFC:
         LCP_RNAK_ADD(PFC,2);
         break;
      case LCP_CI_ACFC:
         LCP_RNAK_ADD(ACFC,2);
         break;
      default:
         if (sizeleft < *inp || *inp < 2) goto badnak;
         sizeleft -= *inp;
         inp += *inp - 1;
      } /* Endswtich */
      code = *inp++;
   } /* Endwhile */

   if (fsm->STATE < PPP_STATE_OPENED) {
      lcp_ptr->RECV_NEG = req_neg;
   } /* Endif */
   return TRUE;

badnak:
   return FALSE;

} /* Endbody */
Exemplo n.º 14
0
DNAT_RULE_STRUCT_PTR DNAT_lookup_rule
   (
      NAT_CFG_STRUCT_PTR      nat_cfg_ptr,
      IP_HEADER_PTR           ip_header_ptr,
      bool                 pub_to_prv
    )
{ /* Body */
   TRANSPORT_UNION            transport;
   DNAT_ELEMENT_STRUCT_PTR    element_ptr;
   _ip_address                source_ip = mqx_ntohl(ip_header_ptr->SOURCE);
   uint32_t                    ip_protocol;
   uint16_t                    source_port, destination_port; /* source port and destination port */
 
   transport.PTR = TRANSPORT_PTR(ip_header_ptr);
   
   ip_protocol = mqx_ntohc(ip_header_ptr->PROTOCOL);

   /* NAT spports ICMP, UDP and TCP transport layer protocols */
   switch (ip_protocol) {
      case IPPROTO_TCP:
          destination_port = mqx_ntohs(transport.TCP_PTR->dest_port);
          source_port = mqx_ntohs(transport.TCP_PTR->source_port);
          break;
      
      case IPPROTO_UDP:
          destination_port = mqx_ntohs(transport.UDP_PTR->DEST_PORT);
          source_port = mqx_ntohs(transport.UDP_PTR->SRC_PORT);
          break;
      
      case IPPROTO_ICMP:
          /* Allow all ICMP request/reply */
          return NULL;
   } /* Endswitch */
     
     
   element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_head(&nat_cfg_ptr->RULE_QUEUE);  

   /*
   ** Check for the target port and then forward the packet to the corresponding 
   ** DNAT rule target ip.
   */
   while (element_ptr != NULL) {
      if (element_ptr->RULE.IP_PROTOCOL == ip_protocol) {
         if (pub_to_prv) {
            if ((destination_port >= element_ptr->RULE.PUBLIC_START_PORT) &&
                (destination_port <= element_ptr->RULE.PUBLIC_END_PORT)) {
               break;
            }
         } else {
            if ((source_ip == element_ptr->RULE.PRIVATE_IP) &&
                (source_port >= element_ptr->RULE.PRIVATE_START_PORT) &&  
                (source_port <= element_ptr->RULE.PRIVATE_END_PORT)) {
               break;  
            }
         }
      }
      element_ptr = (DNAT_ELEMENT_STRUCT_PTR)  _queue_next(&nat_cfg_ptr->RULE_QUEUE, &element_ptr->ELEMENT);
   } /* Endwhile */
   
   if (element_ptr!=NULL) {
      return &element_ptr->RULE;
   } else {
      return NULL;
   }
}/* Endbody */
Exemplo n.º 15
0
static bool LCP_recvconfrej
   (
      PPPFSM_CFG_PTR    fsm
            /* [IN] - State Machine */
   )
{ /* Body */
   LCP_CFG_PTR lcp_ptr = fsm->PRIVATE;
   unsigned char   *inp = fsm->DATA;
   uint32_t     sizeleft = fsm->LENGTH;
   uint32_t     aplen;
   PPP_OPT     req_opt = lcp_ptr->RECV_OPT;
   LCP_NEG     req_neg = lcp_ptr->RECV_NEG;
   unsigned char       code;

#define LCP_RREJ(ci,len) \
      if (sizeleft < len) goto badrej; \
      if (*inp++ != len)  goto badrej; \
      sizeleft -= len;                 \
      req_neg.NEG_ ## ci = 0;          \
      req_opt.ci = PPP_DEFAULT_OPTIONS.ci

   /*
   ** Rej'd codes must be in the same order as they were in the ConfReq
   */

   code = *inp++;

   if (sizeleft && req_neg.NEG_MRU && (code == LCP_CI_MRU)) {
      LCP_RREJ(MRU,4);
      if (req_neg.MRU != mqx_ntohs(inp)) goto badrej; inp += 2;
      code = *inp++;
   } /* Endif */

   if (sizeleft && req_neg.NEG_ACCM && (code == LCP_CI_ACCM)) {
      LCP_RREJ(ACCM,6);
      if (req_neg.ACCM != mqx_ntohl(inp)) goto badrej; inp += 4;
      code = *inp++;
   } /* Endif */

   if (sizeleft && req_neg.NEG_AP && (code == LCP_CI_AP)) {
      switch (req_neg.AP) {
      case PPP_PROT_CHAP: aplen = 5; break;
      default:            aplen = 4; break;
      } /* Endswitch */
      LCP_RREJ(AP,aplen);
      if (req_neg.AP != mqx_ntohs(inp)) goto badrej; inp += 2;
      switch (req_neg.AP) {
      case PPP_PROT_CHAP:
         if (5 != mqx_ntohc(inp)) goto badrej;   /* Only MD5 supported */
         inp++;
         break;
      } /* Endswitch */
      req_opt.AP_Start = PPP_DEFAULT_OPTIONS.AP_Start;
      code = *inp++;
   } /* Endif */

   if (sizeleft && req_neg.NEG_PFC && (code == LCP_CI_PFC)) {
      LCP_RREJ(PFC,2);
      code = *inp++;
   } /* Endif */

   if (sizeleft && req_neg.NEG_ACFC && (code == LCP_CI_ACFC)) {
      LCP_RREJ(ACFC,2);
      code = *inp++;
   } /* Endif */

   if (sizeleft) goto badrej;

   if (fsm->STATE < PPP_STATE_OPENED) {
      lcp_ptr->RECV_OPT = req_opt;
      lcp_ptr->RECV_NEG = req_neg;
   } /* Endif */
   return TRUE;

badrej:
   return FALSE;

} /* Endbody */
Exemplo n.º 16
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 */
Exemplo n.º 17
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 */
Exemplo n.º 18
0
HOSTENT_STRUCT  *DNS_parse_UDP_response
   (
   unsigned char    *buffer_ptr,
   unsigned char    *name_ptr,
   uint16_t       query_type
   )

{  /* Body */

   DNS_MESSAGE_HEADER_STRUCT            *message_head_ptr = NULL;
   DNS_RESPONSE_RR_MIDDLE_STRUCT        *answer_middle;
   INTERNAL_HOSTENT_STRUCT              *host_ptr = &RTCS_HOST;
   unsigned char                                *answer_ptr;
   unsigned char                                *answer_tail;
   unsigned char                                *temp_ptr;
   uint16_t                               response_length, answer_type,
      name_size, number_of_answers, num_queries;
   uint32_t                               i, name_index = 0;
   uint32_t                               j = 0;
   uint32_t                               k = 0;
   uint32_t                               buffer_size;
   uint32_t                              *addr_ptr;
   bool                               unknown_answer_type = FALSE;

   message_head_ptr  = (DNS_MESSAGE_HEADER_STRUCT *)buffer_ptr;
   buffer_size       = sizeof(DNS_MESSAGE_HEADER_STRUCT);
   temp_ptr = buffer_ptr + sizeof( DNS_MESSAGE_HEADER_STRUCT );

   /* Zero the global HOSTENT_STRUCT */
   _mem_zero((char *)host_ptr, sizeof(INTERNAL_HOSTENT_STRUCT));

   /* Get the number of queries. */
   num_queries = mqx_ntohs(message_head_ptr->QDCOUNT);
   for (i = 0; i < num_queries; i++) {
      name_size = 0;
      while( (mqx_ntohc(temp_ptr) != '\0') &&
         name_size < DNS_MAX_CHARS_IN_NAME ) {
         name_size = name_size + mqx_ntohc(temp_ptr) + 1;
         temp_ptr  = temp_ptr  + mqx_ntohc(temp_ptr) + 1;
      } /* Endwhile */
      /* To include the terminating NULL char */
      name_size++;
      buffer_size += (name_size + sizeof(DNS_MESSAGE_TAIL_STRUCT));
      temp_ptr    += (1 + sizeof(DNS_MESSAGE_TAIL_STRUCT));
   } /* Endfor */

   number_of_answers = mqx_ntohs(message_head_ptr->ANCOUNT);
   if (number_of_answers > DNS_MAX_NAMES ) {
      number_of_answers = DNS_MAX_NAMES;
   } /* Endif */

   host_ptr->HOSTENT.h_aliases   = &host_ptr->ALIASES[0];
   host_ptr->HOSTENT.h_addr_list = (char **)&host_ptr->ADDRESSES[0];
   host_ptr->ADDRESSES[0]        = NULL;
   host_ptr->HOSTENT.h_name      = NULL;
   host_ptr->HOSTENT.h_length    = sizeof( _ip_address );

   for (i = 0; (i < number_of_answers) && (j < DNS_MAX_ADDRS) &&
       (k < DNS_MAX_NAMES); i++ )
   {
      answer_ptr = temp_ptr;
      name_size  = 0;

      while( (mqx_ntohc(temp_ptr) != '\0') &&
             name_size < DNS_MAX_CHARS_IN_NAME &&
             !(mqx_ntohc(temp_ptr) & DNS_COMPRESSED_NAME_MASK)) {
         name_size += mqx_ntohc(temp_ptr);
         temp_ptr += mqx_ntohc(temp_ptr) + 1;
      } /* Endwhile */

      if ( mqx_ntohc(temp_ptr) & DNS_COMPRESSED_NAME_MASK ) {
         temp_ptr++;
      }/* Endif */

      temp_ptr++;
      answer_middle   = (DNS_RESPONSE_RR_MIDDLE_STRUCT *)temp_ptr;
      response_length = mqx_ntohs(answer_middle->RDLENGTH);
      answer_type     = mqx_ntohs(answer_middle->TYPE);
      temp_ptr       += sizeof(DNS_RESPONSE_RR_MIDDLE_STRUCT);
      answer_tail     = temp_ptr;
      temp_ptr       += response_length;

      switch ( answer_type ) {

         case DNS_A:
            if ( host_ptr->HOSTENT.h_name == NULL ) {
               host_ptr->HOSTENT.h_name =
                  (char *)DNS_parse_answer_name_to_dotted_form(
                  buffer_ptr, answer_ptr, name_index );
               name_index++;
            } /* Endif */

            RTCS_HOST_ADDRS[j] = mqx_ntohl((unsigned char *)answer_tail);
            /*
            ** j is used in case BOTH CNAME and A data is received.  If CNAME
            ** answer is first, will write into wrong address space if using
            ** i.
            */
            host_ptr->ADDRESSES[j] = &RTCS_HOST_ADDRS[j];
            j++;
            /*
            ** This is to assure that the first IP address used is the first
            ** one that was given
            */
            host_ptr->IP_address = *host_ptr->ADDRESSES[0];
            break;

         case DNS_PTR:
            if (query_type == DNS_PTR) {
               if (host_ptr->HOSTENT.h_name != NULL) {
                  host_ptr->ALIASES[k] = host_ptr->HOSTENT.h_name;
                  k++;
               } /* Endif */
               host_ptr->HOSTENT.h_name =
                  (char *)DNS_parse_answer_name_to_dotted_form(
                  buffer_ptr, answer_tail, name_index );
               name_index++;
               addr_ptr = RTCS_mem_alloc_zero( sizeof( _ip_address ));
               if ( addr_ptr == NULL ) {
                  RTCS_log_error(ERROR_DNS, RTCSERR_DNS_UNABLE_TO_ALLOCATE_MEMORY,
                                 0, 0, 0);
                  return( NULL );
               }/* Endif */

               *addr_ptr = *((_ip_address *)name_ptr);
               host_ptr->ADDRESSES[j] = addr_ptr;
               j++;
               host_ptr->IP_address = *host_ptr->ADDRESSES[0];
            } else {
               host_ptr->ALIASES[k] = (char *)
                     DNS_parse_answer_name_to_dotted_form( buffer_ptr,
                     answer_tail, name_index );
               name_index++;
               k++;
            } /* Endif */
            break;

         case DNS_CNAME:
            /* the k is used for ALIASES as the j is used for ADDRESSES */
            host_ptr->ALIASES[k] = (char *)
               DNS_parse_answer_name_to_dotted_form(
               buffer_ptr, answer_tail, name_index );
            name_index++;
            k++;
            break;

         default:
            unknown_answer_type = TRUE;
      } /* Endswitch */

      if ( unknown_answer_type == TRUE ) {
         break;
      }/* Endif */

      host_ptr->ADDRESSES[j]       = NULL;
      host_ptr->ALIASES[k]         = NULL;
      host_ptr->HOSTENT.h_addrtype = mqx_ntohs(answer_middle->CLASS);

   } /* Endfor */

   if ( number_of_answers == 0 ) {
      return( NULL );
   } /* Endif */

   return( &RTCS_HOST.HOSTENT );

} /* Endbody */
Exemplo n.º 19
0
unsigned char *TFTP_read
   (
      uint32_t    *size
         /* [OUT] number of bytes read, or error code */
   )
{ /* Body */
   uint32_t        sock;
   sockaddr_in    remote_addr;
   uint16_t        remote_size;
   uint16_t        ack_block;
   uint16_t        pkt_op, pkt_block;
   uint32_t        pkt_size;
   uint32_t        time_left;
   bool        expired;
#if TFTP_TIMEOUT_RETRIES
   uint32_t        retries = 0;
#endif

   ack_block = mqx_ntohs(TFTP_config.ACK.BLOCK);
   TFTP_timeout_restart(&TFTP_config.TIMEOUT);

   for (;;) {

      /* Check for timeout */
      time_left = TFTP_timeout_left(&TFTP_config.TIMEOUT, &expired);
      if (expired) {
#if TFTP_TIMEOUT_RETRIES
         retries++;
         if (retries > TFTP_TIMEOUT_RETRIES) {
            *size = RTCSERR_TFTP_TIMEOUT;
            TFTP_close();
            return NULL;
         } /* Endif */
#endif
         /* Retransmit the last packet */
         TFTP_RESEND();
      } /* Endif */

      /* Wait for a packet */
      sock = TFTP_WAIT(time_left);

      /* Timeout -- retransmit last packet */
      if (sock != TFTP_config.SOCK) {
         continue;
      } /* Endif */

      remote_size = sizeof(remote_addr);
      pkt_size = TFTP_RECV(TFTP_config.PACKET);

      pkt_op    = mqx_ntohs(TFTP_config.PACKET.HEAD.OP);
      pkt_block = mqx_ntohs(TFTP_config.PACKET.HEAD.BLOCK);

      /* Check source address of received packet */
      if (remote_addr.sin_addr.s_addr != TFTP_config.SADDR.sin_addr.s_addr) {
         continue;
      } /* Endif */

      /* Validate source port */
      if (ack_block && remote_addr.sin_port != TFTP_config.SADDR.sin_port) {
         TFTP_SEND(TFTP_config.SOCK, _tftp_error_tid, remote_addr);
         continue;
      } /* Endif */

      /* Check size of received packet */
      if (pkt_size < sizeof(TFTP_HEADER)) {
         TFTP_SEND(TFTP_config.SOCK, _tftp_error_op, remote_addr);
         *size = RTCSERR_TFTP_ERROR + TFTPERR_ILLEGAL_OP;
         TFTP_close();
         return NULL;
      } /* Endif */

      /* Check for error packet */
      if (pkt_op == TFTPOP_ERROR) {
         *size = RTCSERR_TFTP_ERROR + pkt_block;
         TFTP_close();
         return NULL;
      } /* Endif */

      /* Check for data packet */
      if ((pkt_op != TFTPOP_DATA)
       || (pkt_size > sizeof(TFTP_PACKET))) {
         TFTP_SEND(TFTP_config.SOCK, _tftp_error_op, remote_addr);
         *size = RTCSERR_TFTP_ERROR + TFTPERR_ILLEGAL_OP;
         TFTP_close();
         return NULL;
      } /* Endif */

      /* Check for retransmitted packet */
      if (pkt_block == ack_block) {
         TFTP_timeout_restart(&TFTP_config.TIMEOUT);
         TFTP_SEND(TFTP_config.SOCK, TFTP_config.ACK, TFTP_config.SADDR);
         continue;
      } /* Endif */

      /* Aknowledge also packets with lower id, some servers do retransmit them until they get an ack */
      if (pkt_block < ack_block) {
         TFTP_timeout_restart(&TFTP_config.TIMEOUT);
         mqx_htons(TFTP_config.ACK.BLOCK, pkt_block);
         TFTP_SEND(TFTP_config.SOCK, TFTP_config.ACK, TFTP_config.SADDR);
         mqx_htons(TFTP_config.ACK.BLOCK, ack_block); /* Restore id of last acknowledged packet */
         continue;
      } /* Endif */

      /* Drop unexpected packets */
      if (pkt_block > ack_block+1) {
         /* Some server do send more than one packet at a time, these will eventually retransmitted */
         continue;
      }

      /* We have the next packet */
      break;
   } /* Endfor */

   /* Update the adaptive timeout */
   TFTP_timeout_update(&TFTP_config.TIMEOUT);

   /* Free the original RRQ */
   if (!ack_block) {
      TFTP_config.SADDR.sin_port = remote_addr.sin_port;
      _mem_free(TFTP_config.RRQ_PTR);
      TFTP_config.RRQ_PTR = NULL;
   } /* Endif */

   /* ACK it */
   ack_block++;
   mqx_htons(TFTP_config.ACK.BLOCK, ack_block);
   TFTP_SEND(TFTP_config.SOCK, TFTP_config.ACK, TFTP_config.SADDR);
   TFTP_config.LAST = (pkt_size < sizeof(TFTP_PACKET));

   /* Return the data */
   *size = pkt_size - sizeof(TFTP_HEADER);
   return TFTP_config.PACKET.DATA;

} /* Endbody */