예제 #1
0
파일: tftputil.c 프로젝트: zhouglu/K60F120M
uint_32 TFTP_timeout_update
   (
      TFTP_TO_STRUCT_PTR   to
   )
{ /* Body */
   uint_32 time, time_elapsed;
   int_32 error;

   time = RTCS_time_get();
   if (to->UPDATE) {
      time_elapsed = RTCS_timer_get_interval(to->TS, time);
      error = time_elapsed - to->M;
      to->M += error >> 3;
      if (!to->M) to->M++;
      if (error < 0) error = -error;
      error -= to->D;
      to->D += error >> 2;
      if (!to->D) to->D++;
      to->TO = to->M + (to->D << 2);
   } /* Endif */
예제 #2
0
void NAT_event_tick
   (
      TCPIP_EVENT_PTR   tcpip_event_ptr,   /* [IN] Controlling event           */
      boolean           force    /* [IN] Force expiry of first event */
   )
{ /* Body */
   NAT_EVENT_HEAD_PTR   nat_event_head_ptr = tcpip_event_ptr->PRIVATE;
   uint_32              msec, elapsed;

   msec = RTCS_time_get();
   
   if (nat_event_head_ptr->FIRST) {
   
      if (force) {
         elapsed = nat_event_head_ptr->FIRST->TIME;   
      } else {
         elapsed = RTCS_timer_get_interval(nat_event_head_ptr->TIMESTAMP, msec); 
      } /* Endif */

      if (nat_event_head_ptr->FIRST->TIME <= elapsed) {
         nat_event_head_ptr->FIRST->TIME = 0;
      } else { 
         nat_event_head_ptr->FIRST->TIME -= elapsed;
      } /* Endif */
      
      if (nat_event_head_ptr->TIMEDELTA <= elapsed) {
         nat_event_head_ptr->TIMEDELTA = 0;
      } else { 
         nat_event_head_ptr->TIMEDELTA -= elapsed;
      } /* Endif */
      
   } /* Endif */
   
   nat_event_head_ptr->TIMESTAMP = msec;

} /* Endbody */
예제 #3
0
void PPP_tx_task
   (
      void       *handle,
            /* [IN] - the PPP state structure */
      void       *creator
            /* [IN] - the creation information */
   )
{ /* Body */

#if RTCSCFG_ENABLE_IP4

   PPP_CFG_PTR       ppp_ptr = handle;
   uint32_t           ctrl;
   bool           state;
   PPP_OPT           opt;
   PCB_PTR           pcb;
   uint32_t           pcbopt;
   PPP_MESSAGE_PTR   message, xmithead, * xmitnode;
   uint32_t           timebefore, timeafter;
   bool           wait;
   int32_t            timeout;
   uint16_t           protocol;
   _queue_id         queue;
   void             *param;

   /* Obtain a message queue so that PPP_send() can reach us */
   queue = RTCS_msgq_open(0, 0);
   if (queue == 0) {
      RTCS_task_exit(creator, RTCSERR_PPP_OPEN_QUEUE_FAILED);
   } /* Endif */

   RTCS_task_resume_creator(creator, PPP_OK);

   ppp_ptr->MSG_QUEUE = queue;

   xmithead = NULL;
   timebefore = RTCS_time_get();

#define PPPTX_DISCARD(msg) \
            (msg)->PCB->FREE = (msg)->ORIG_FREE;   \
            PCB_free((msg)->PCB);                  \
            RTCS_msg_free(msg)

   for(;;)
   {

      /**********************************************************
      **
      **    Wait for a packet to send
      **
      */

      wait = TRUE;
      timeout = 0;

      /* Check if a packet is waiting for retransmission */
      if (xmithead) {

         /* Measure elapsed time */
         timeafter = RTCS_time_get();
         timeout = RTCS_timer_get_interval(timebefore, timeafter); 
         timebefore = timeafter;
         xmithead->DELTA -= timeout;

         /* If its timer has expired, send it */
         timeout = xmithead->DELTA;
         if (timeout <= 0) {
            message = NULL;
            wait = FALSE;
         } /* Endif */
      } /* Endif */

      /*
      ** There are three cases at this point:
      **    1) Retransmission queue is empty
      **          (wait == TRUE,  timeout == 0, message == ?)
      **    2) Retransmission queue is nonempty, positive timeout
      **          (wait == TRUE,  timeout > 0,  message == ?)
      **    3) Retransmission queue is nonempty, nonpositive timeout,
      **       i.e., head of retransmission queue timed out
      **          (wait == FALSE, timeout == 0, message == NULL)
      */

      /* If there are no expired messages, block */
      if (wait) {
         message = RTCS_msgq_receive(queue, timeout, ppp_ptr->MSG_POOL);
      } /* Endif */

      /*
      ** There are two cases at this point:
      **    1) We got a message from _msgq_receive
      **          (message != NULL)
      **    2) Head of retransmission queue timed out
      **          (message == NULL)
      */

      /* We got a packet to send */
      if (message) {

         /* Control packets restart or stop retransmission */
         ctrl = message->COMMAND;

         if (ctrl == PPPCMD_SHUTDOWN) {
            param = message->PARAM;
            /* Free the message we just got */
            RTCS_msg_free(message);
            for (xmitnode = &xmithead;;){
               if (*xmitnode == NULL) {
                  break;
               } else {
                 /* unlink */
                 message = *xmitnode;
                 *xmitnode = message->NEXT;
                 /* Free the message from the list */
                 PPPTX_DISCARD(message);
               } /* Endif */
            } /* Endfor */
            RTCS_msgq_close(queue);
            /* Unblock PPP_shutdown() */
            RTCS_sem_post(param);
            /* Kill self */
            return;
         } /* Endif */
         
         if (ctrl != PPPCMD_SEND) {
            protocol = message->PROTOCOL;
            RTCS_msg_free(message);

            /*
            ** Search the retransmission queue for a packet
            ** matching the protocol field of the control message
            */
            for (xmitnode = &xmithead;;
                 xmitnode = &(*xmitnode)->NEXT) {
               if (*xmitnode == NULL) {
                  break;
               } else if ((*xmitnode)->PROTOCOL == protocol) {
                  message = *xmitnode;
                  switch (ctrl) {
                  case PPPCMD_RESTART:
                     message->TIMEOUT = _PPP_MIN_XMIT_TIMEOUT;
                     message->RETRY = _PPP_MAX_CONF_RETRIES;
                     break;
                  case PPPCMD_STOP:
                     if (message->NEXT) {
                        message->NEXT->DELTA += message->DELTA;
                     } /* Endif */
                     *xmitnode = message->NEXT;
                     PPPTX_DISCARD(message);
                     break;
                  } /* Endswitch */
                  break;
               } /* Endif */
            } /* Endfor */

            continue;
         } /* Endif */

         /* Save the PCB's FREE field */
         message->ORIG_FREE = message->PCB->FREE;
         if (message->TIMEOUT) {
            message->PCB->FREE = PPP_tx_pcbfree;
         } /* Endif */

      /* Receive timed out -- get the head of the retransmission queue */
      } else {
         message = xmithead;
         xmithead = message->NEXT;
         if (xmithead) {
            xmithead->DELTA += message->DELTA;
         } /* Endif */

         /* Generate a TO event */
         if (message->CALL) {
            message->CALL(message->PARAM, message->PCB, message->RETRY == 1);
         } /* Endif */

         /* RETRY == 0 means retry forever */
         if (message->RETRY) {

            /* When the retry count reaches zero, discard the packet */
            if (!--message->RETRY) {
               PPPTX_DISCARD(message);
               continue;
            } /* Endif */
         } /* Endif */

         /* Use exponential backoff when retransmitting */
         message->TIMEOUT <<= 1;
         if (message->TIMEOUT > _PPP_MAX_XMIT_TIMEOUT) {
            message->TIMEOUT = _PPP_MAX_XMIT_TIMEOUT;
         } /* Endif */
      } /* Endif */

      /**********************************************************
      **
      **    We have a packet -- validate it
      **
      */

      /* Take a snapshot of the current state and send options */
      PPP_mutex_lock(&ppp_ptr->MUTEX);
      state = ppp_ptr->LINK_STATE;
      opt = *ppp_ptr->SEND_OPTIONS;
      PPP_mutex_unlock(&ppp_ptr->MUTEX);

      /* Send the data packet (unless the link is not open) */
      if (!state && message->PROTOCOL != PPP_PROT_LCP) {
         PPPTX_DISCARD(message);
         ppp_ptr->ST_TX_DISCARDED++;
         continue;
      } /* Endif */

      /**********************************************************
      **
      **    We have a valid packet -- send it
      **
      */

      /* LCP control packets are always sent with default options */
      if (message->PROTOCOL == PPP_PROT_LCP
       && message->PCB->FRAG[0].FRAGMENT[2] >= 1
       && message->PCB->FRAG[0].FRAGMENT[2] <= 7) {
         pcbopt = 1;
      } else {
         pcbopt = 0;
      } /* Endif */

      pcb = message->PCB;

      /* Only data packets are compressed */
      /* Start CR 2296 */
      //if (((message->PROTOCOL & 0xC000) == 0) && opt.CP) {
      /* End CR 2296 */
      //   pcb = opt.CP->CP_comp(&ppp_ptr->CCP_STATE.SEND_DATA, pcb, ppp_ptr, &opt);
      //   mqx_htons(pcb->FRAG[0].FRAGMENT, PPP_PROT_CP);
      //} /* Endif */

      _iopcb_write(ppp_ptr->DEVICE, pcb, pcbopt);

      /**********************************************************
      **
      **    Packet is sent -- update retransmission queue
      **
      */

      /* Free the buffer unless it may need to be retransmitted */
      if (message->TIMEOUT) {

         /* Measure elapsed time */
         timeafter = RTCS_time_get();
         timeout = RTCS_timer_get_interval(timebefore, timeafter); 
         timebefore = timeafter;
         if (xmithead) {
            xmithead->DELTA -= timeout;
         } /* Endif */

         /* Insert packet into proper place in retransmission queue */
         for (message->DELTA = message->TIMEOUT,    xmitnode = &xmithead;;
              message->DELTA -= (*xmitnode)->DELTA, xmitnode = &(*xmitnode)->NEXT) {
            if (*xmitnode == NULL) {
               /* Add packet at tail of queue */
               message->NEXT = NULL;
               *xmitnode = message;
               break;
            } else if ((*xmitnode)->DELTA > message->TIMEOUT) {
               /* Insert packet in middle (possibly head) of queue */
               (*xmitnode)->DELTA -= message->DELTA;
               message->NEXT = *xmitnode;
               *xmitnode = message;
               break;
            } /* Endif */
         } /* Endfor */

      } else {
         /* PCB has already been freed by _iopcb_write() */
         RTCS_msg_free(message);
      } /* Endif */

   } /* Endfor */
#endif /* RTCSCFG_ENABLE_IP4 */
   
} /* Endbody */
예제 #4
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 */
예제 #5
0
void TCPIP_task
   (
      void    *dummy,
      void    *creator
   )
{ /* Body */
   TCPIP_CFG_STRUCT           TCPIP_cfg;
   RTCS_DATA_PTR              RTCS_data_ptr;
   uint32_t                    i;
   TCPIP_MESSAGE_PTR          tcpip_msg;
   uint32_t                    timeout = 1, timebefore, timeafter, timedelta;
   uint32_t                    status;           /* Return status */
   _queue_id                  tcpip_qid;
   
    RTCSLOG_FNE2(RTCSLOG_FN_TCPIP_task, creator);

   RTCS_data_ptr = RTCS_get_data();
   RTCS_setcfg(TCPIP, &TCPIP_cfg);

   TCPIP_cfg.status = RTCS_OK;

   tcpip_qid = RTCS_msgq_open(TCPIP_QUEUE, 0);
   if (tcpip_qid == 0) {
      RTCS_task_exit(creator, RTCSERR_OPEN_QUEUE_FAILED);
   } /* Endif */

   RTCS_data_ptr->TCPIP_TASKID = RTCS_task_getid();

   /*
   ** Initialize the Time Service
   */
   TCP_tick = TCPIP_fake_tick;
   TCPIP_Event_init();
   timebefore = RTCS_time_get();

   /*
   ** Allocate a block of PCBs
   */
   status = RTCSPCB_init();
   if (status != RTCS_OK) {
      RTCS_task_exit(creator, status);
   } /* Endif */
    
    IF_FREE       = NULL;
    
   /*
   ** Initialize the protocols
   */
   
#if RTCSCFG_ENABLE_IP4
    /*********************************************
    *   Initialize IPv4
    **********************************************/
    status = IP_init();
    if (status)
    {
        RTCS_task_exit(creator, status);
    } 

#if RTCSCFG_ENABLE_ICMP

    status = ICMP_init();
    if (status)
    {
        RTCS_task_exit(creator, status);
    }
   
#endif /* RTCSCFG_ENABLE_ICMP */

    ARP_init();
    
    BOOT_init();

#endif /* RTCSCFG_ENABLE_IP4 */

#if RTCSCFG_ENABLE_IP6

    /*********************************************
    *   Initialize IPv6
    **********************************************/
    status = IP6_init();
    if (status)
    {
      RTCS_task_exit(creator, status);
    } 

    /* Init ICMP6. */ 
    status = ICMP6_init(); //TBD Add it to RTCS6_protocol_table
    if (status)
    {
        RTCS_task_exit(creator, status);
    } 
    
#endif /* RTCSCFG_ENABLE_IP6*/

#if (RTCSCFG_ENABLE_IP_REASSEMBLY && RTCSCFG_ENABLE_IP4) || (RTCSCFG_ENABLE_IP6_REASSEMBLY && RTCSCFG_ENABLE_IP6)
    /* Initialize the reassembler */
    status = IP_reasm_init();
    if (status)
    {
        RTCS_task_exit(creator, status);
    } 
#endif

    /* Add loopback interface.*/
    status = IPLOCAL_init ();    
    if (status)
    {
        RTCS_task_exit(creator, status);
    };

   for (i = 0; RTCS_protocol_table[i]; i++) {
      status = (*RTCS_protocol_table[i])();
      if (status) {
         RTCS_task_exit(creator, status);
      } /* Endif */
   } /* Endfor */

   _RTCS_initialized= TRUE;
   RTCS_task_resume_creator(creator, RTCS_OK);

    while (1)
    {
        TCPIP_EVENT_PTR queue = TCPIP_Event_head;
        
        tcpip_msg = (TCPIP_MESSAGE_PTR)RTCS_msgq_receive(tcpip_qid, timeout, RTCS_data_ptr->TCPIP_msg_pool);
      
        if (tcpip_msg)
        {
            if (NULL != tcpip_msg->COMMAND)
            {
                tcpip_msg->COMMAND(tcpip_msg->DATA);
            }
            RTCS_msg_free(tcpip_msg);
        }
        
        timeout = TCP_tick();
        timeafter = RTCS_time_get();
        
        /* If head changed set time delta to zero to prevent immidiate event */
        if (queue == TCPIP_Event_head)
        {
            timedelta = RTCS_timer_get_interval(timebefore, timeafter); 
        }
        else
        {
            timedelta = 0;
        }
        
        timebefore = timeafter;
        timedelta = TCPIP_Event_time(timedelta);
        
        if (timedelta != 0)
        {
            if ((timedelta < timeout) || (timeout == 0))
            {
                timeout = timedelta;
            }
        }
    }
} /* Endbody */
예제 #6
0
파일: icmp.c 프로젝트: tsbiberdorf/MqxSrc
void ICMP_service
   (
      RTCSPCB_PTR    pcb,        /* [IN/OUT] incoming packet */
      pointer        dummy       /* [IN]     not used        */
   )
{ /* Body */
   ICMP_CFG_STRUCT_PTR  ICMP_cfg_ptr;
   ICMP_HEADER_PTR      packet;
   _ip_address          source, dest;
   uint_32              error;
   uint_16              chksum;
   uchar                type;


   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 = 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 */

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

   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  = ntohl(rdpacket->DATA);
         origdest = ntohl(rdpacket->IP.DEST);

         // If we receive a redirect to ourselves, silently discard it
         if (IP_is_local(NULL, gateway)) {
            IF_ICMP_STATS_ENABLED(ICMP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++);
            // Might want to add a counter here

         } 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:

      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, (uint_32)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, (uint_32)pcb));
         RTCSLOG_PCB_FREE(pcb, error);
         RTCSPCB_free(pcb);
         return;
      } /* Endif */

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

      /* 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, 0);
      pcb = NULL;
      break;

   case ICMPTYPE_ECHO_REPLY:
      { /* Scope */
         ICMP_ECHO_HEADER_PTR echopacket = (ICMP_ECHO_HEADER_PTR)packet;
         ICMP_PARM_PTR        parms;
         uint_16              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  = ntohs(echopacket->ID);
         seq = ntohs(echopacket->SEQ);

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

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

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

               TCPIP_Event_cancel(&parms->EXPIRE);

               /* calculate round trip time */
               parms->timeout = RTCS_timer_get_interval(parms->timeout, RTCS_time_get());

               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;
         uint_32             len, remain;
         boolean             discard = TRUE;
         uchar               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)((uchar_ptr)packet + sizeof(ICMP_HEADER) + 4);
            remain -= sizeof(ICMP_HEADER) + 4;

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

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

               /* Get next header */
               ip = (IP_HEADER_PTR)((uchar_ptr)(ip) + len);
               remain -= len;
               source = ntohl(ip->SOURCE);

               discard = IP_is_local(NULL, source);

            } while(discard);

            len = (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 = 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, 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 */