Beispiel #1
0
void DNAT_get_next_rule_internal
   (
      DNAT_PARM_PTR           dparm_ptr      /* [IN] */   
   )
{ /* Body */
   NAT_CFG_STRUCT_PTR         nat_cfg_ptr = RTCS_getcfg(NAT);
   DNAT_ELEMENT_STRUCT_PTR    prev_element_ptr, next_element_ptr;

   if (nat_cfg_ptr == NULL) {
      RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_NOT_INITIALIZED);
      return;
   }

        
   prev_element_ptr = NULL;
   next_element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_head(&nat_cfg_ptr->RULE_QUEUE);  
   
   while ((next_element_ptr != NULL) && 
          (next_element_ptr->RULE.PRIORITY >= dparm_ptr->RULE.PRIORITY)) {
      prev_element_ptr = next_element_ptr;
      next_element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_next(&nat_cfg_ptr->RULE_QUEUE, &prev_element_ptr->ELEMENT);
   }
   
   if (next_element_ptr == NULL) {
      RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_END_OF_RULES);
   } else {
      dparm_ptr->RULE    = next_element_ptr->RULE;

      RTCSCMD_complete(dparm_ptr, RTCS_OK);
   }
}/* Endbody */
void RTCS_remove_trap_receiver_internal
   (
      TRAP_PARM  *parm
   )
{ /* Body */
   volatile SNMP_PARSE_PTR    snmpcfg = SNMP_get_data();
   _ip_address       ip_addr = parm->address;
   _mqx_uint         i;
   
   /* Traverse the receivers list looking for our entry */
   for (i = 0; i < SNMPCFG_MAX_TRAP_RECEIVERS; i++) {
      if (snmpcfg->trap_receiver_list[i] == ip_addr) {
         /* Found it */
         snmpcfg->trap_receiver_list[i] = 0;
         break;
      } /* Endif */     
   } /* Endfor */
      
   if (i < SNMPCFG_MAX_TRAP_RECEIVERS) {
      RTCSCMD_complete(parm, RTCS_OK);
   } else {
      RTCSCMD_complete(parm, RTCSERR_TRAP_REMOVE_FAILED);
   } /* Endif */

} /* Endbody */
Beispiel #3
0
void  DNAT_delete_rule_internal
   (
      DNAT_PARM_PTR           dparm_ptr      /* [IN] */
    )
{ /* Body */   
   NAT_CFG_STRUCT_PTR      nat_cfg_ptr = RTCS_getcfg(NAT);
   DNAT_ELEMENT_STRUCT_PTR element_ptr;
   uint32_t                 priority = dparm_ptr->RULE.PRIORITY;

   if (nat_cfg_ptr == NULL) {
      RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_NOT_INITIALIZED);
      return;
   }

   element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_head(&nat_cfg_ptr->RULE_QUEUE); 

   while (element_ptr != NULL) {
      if (element_ptr->RULE.PRIORITY == priority) {
         _queue_unlink(&nat_cfg_ptr->RULE_QUEUE, &element_ptr->ELEMENT); 
         _mem_free((void *)element_ptr);
         RTCSCMD_complete(dparm_ptr, RTCS_OK);
         return;
      } 
      element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_next(&nat_cfg_ptr->RULE_QUEUE, &element_ptr->ELEMENT);
   }
   
   RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_INVALID_RULE);
} /* Endbody */
void RTCS_insert_trap_receiver_internal
   (
      TRAP_PARM  *parm
   )
{ /* Body */
   volatile SNMP_PARSE_PTR    snmpcfg = SNMP_get_data();
   _ip_address       ip_addr = parm->address;
   _mqx_uint         i;
   
   /* Find an empty entry in the receivers list */
   for (i = 0; i < SNMPCFG_MAX_TRAP_RECEIVERS; i++) {
      if (snmpcfg->trap_receiver_list[i] == 0) {
         /* Found a space */
         snmpcfg->trap_receiver_list[i] = ip_addr;
         break;
      } /* Endif */     
   } /* Endfor */
      
   if (i < SNMPCFG_MAX_TRAP_RECEIVERS) {
      RTCSCMD_complete(parm, RTCS_OK);
   } else {
      RTCSCMD_complete(parm, RTCSERR_TRAP_INSERT_FAILED);
   } /* Endif */

} /* Endbody */
Beispiel #5
0
void NAT_remove_network_internal
   (
      NAT_PARM_PTR   parm_ptr   /* [IN] Initialization parameters */
   )
{ /* Body */
   NAT_CFG_STRUCT_PTR      nat_cfg_ptr = RTCS_getcfg(NAT);
   uint_32                 error;

   // Make sure NAT is already up
   if (nat_cfg_ptr == NULL) {
      error = RTCSERR_NAT_NOT_INITIALIZED;

   /* 
   ** Make sure the netmask is valid. We use the fact that 
   ** (x & x+1) == 0 <=> x = 2^n-1.
   */
   } else if (~parm_ptr->IP_MASK & (~parm_ptr->IP_MASK + 1)) {
      error = RTCSERR_INVALID_PARAMETER;

   /* Make sure other parameters have been supplied */
   } else if (!parm_ptr->IP_PRV) {
      error = RTCSERR_INVALID_PARAMETER;

   } else {
      // Try to remove the private network
      error=NAT_remove_private_network(&nat_cfg_ptr->PRIVATE_NETWORKS, parm_ptr->IP_PRV, parm_ptr->IP_MASK);
   }

   RTCSCMD_complete(parm_ptr, error);      

} /* Endbody */
Beispiel #6
0
void NAT_init_internal
   (
      NAT_PARM_PTR   parm_ptr   /* [IN] Initialization parameters */
   )
{
   RTCSCMD_complete(parm_ptr, NAT_init_internal2(parm_ptr));      
}
Beispiel #7
0
/*FUNCTION*-------------------------------------------------------------
*
* Function Name   : ICMP_expire_echo
* Returned Values :
* Comments  :
*     Called by the Timer.  Expire a ICMP echo request.
*
*END*-----------------------------------------------------------------*/
boolean ICMP6_expire_echo(TCPIP_EVENT_PTR   event)
{
   ICMP_ECHO_PARAM_PTR         parms = event->PRIVATE;

   RTCSCMD_complete(parms, RTCSERR_ICMP_ECHO_TIMEOUT);

   return FALSE;
}
Beispiel #8
0
void IPCP_bind
   (
      TCPIP_PARM_IPCP _PTR_ parms
   )
{ /* Body */
   IP_IF_PTR            if_ptr = parms->handle;
   IPCP_CFG_STRUCT_PTR  ipcp_ptr = if_ptr->HANDLE;
   _ppp_handle          handle = ipcp_ptr->HANDLE;
   uint_32              error;

   ipcp_ptr->CALLUP  = IPCP_lowerup;
   ipcp_ptr->PARAMUP = &ipcp_ptr->FSM;
   ipcp_ptr->CALLDOWN  = IPCP_lowerdown;
   ipcp_ptr->PARAMDOWN = &ipcp_ptr->FSM;

   error = PPP_setcall(handle, PPP_CALL_LINK_UP, &ipcp_ptr->CALLUP, &ipcp_ptr->PARAMUP);
   if (!error) {
      error = PPP_setcall(handle, PPP_CALL_LINK_DOWN, &ipcp_ptr->CALLDOWN, &ipcp_ptr->PARAMDOWN);
      if (error) {
         PPP_setcall(handle, PPP_CALL_LINK_UP, &ipcp_ptr->CALLUP, &ipcp_ptr->PARAMUP);
      } /* Endif */
   } /* Endif */

   if (!error) {
      ipcp_ptr->IP_UP    = parms->data->IP_UP;
      ipcp_ptr->IP_DOWN  = parms->data->IP_DOWN;
      ipcp_ptr->IP_PARAM = parms->data->IP_PARAM;

      ipcp_ptr->INIT.ACCEPT_LOCAL_ADDR  = parms->data->ACCEPT_LOCAL_ADDR;
      ipcp_ptr->INIT.LOCAL_ADDR         = parms->data->LOCAL_ADDR;
      ipcp_ptr->INIT.ACCEPT_REMOTE_ADDR = parms->data->ACCEPT_REMOTE_ADDR;
      ipcp_ptr->INIT.REMOTE_ADDR        = parms->data->REMOTE_ADDR;
      ipcp_ptr->INIT.DEFAULT_NETMASK    = parms->data->DEFAULT_NETMASK;
      ipcp_ptr->INIT.NETMASK            = parms->data->NETMASK;
      ipcp_ptr->INIT.DEFAULT_ROUTE      = parms->data->DEFAULT_ROUTE;
      ipcp_ptr->INIT.NEG_LOCAL_DNS      = parms->data->NEG_LOCAL_DNS;
      ipcp_ptr->INIT.ACCEPT_LOCAL_DNS   = parms->data->ACCEPT_LOCAL_DNS;
      ipcp_ptr->INIT.LOCAL_DNS          = parms->data->LOCAL_DNS;
      ipcp_ptr->INIT.NEG_REMOTE_DNS     = parms->data->NEG_REMOTE_DNS;
      ipcp_ptr->INIT.ACCEPT_REMOTE_DNS  = parms->data->ACCEPT_REMOTE_DNS;
      ipcp_ptr->INIT.REMOTE_DNS         = parms->data->REMOTE_DNS;

      /* Start IPCP */
      PPPFSM_open(&ipcp_ptr->FSM, 0);

      /* Open the link */
      error = PPP_open(handle, 0);

   } /* Endif */

   RTCSCMD_complete(parms, PPP_TO_RTCS_ERROR(error));

} /* Endbody */
Beispiel #9
0
void BOOTP_open
   (
      TCPIP_PARM_BOOTP _PTR_ parms
   )
{ /* Body */
   IP_IF_PTR      if_ptr = (IP_IF_PTR)parms->handle;
   BOOTP_CFG_PTR  bootp = (BOOTP_CFG_PTR) &parms->config;
   uint_32        error;

   error = BOOT_open(BOOT_service);
   if (error) {
      RTCSCMD_complete(parms, error);
      return;
   } /* Endif */

   if_ptr->BOOTFN = BOOTP_service;

   /* Pick a random transaction ID */
   bootp->XID = RTCS_rand();

   /* Set initial timeout */
   bootp->TIMEOUT = BOOTP_TIMEOUT_MIN;
   bootp->SECS = 0;

   /* Build a BOOTREQUEST packet */
   htonc(bootp->PACKET.OP,    BOOTPOP_BOOTREQUEST);
   htonc(bootp->PACKET.HTYPE, if_ptr->DEV_TYPE);
   htonc(bootp->PACKET.HLEN,  if_ptr->DEV_ADDRLEN);
   htonc(bootp->PACKET.HOPS,  0);
   htonl(bootp->PACKET.XID,   bootp->XID);
   htons(bootp->PACKET.FLAGS, 0x8000);
   htonl(bootp->PACKET.CIADDR, INADDR_ANY);
   htonl(bootp->PACKET.YIADDR, INADDR_ANY);
   htonl(bootp->PACKET.SIADDR, INADDR_ANY);
   htonl(bootp->PACKET.GIADDR, INADDR_ANY);

   _mem_zero(bootp->PACKET.CHADDR, sizeof(bootp->PACKET.CHADDR));
   _mem_copy(if_ptr->DEV_ADDR, bootp->PACKET.CHADDR, if_ptr->DEV_ADDRLEN);

   /* Start the retransmission timer to start sending immediately */
   bootp->RESEND.TIME    = 0;
   bootp->RESEND.EVENT   = BOOTP_send;
   bootp->RESEND.PRIVATE = if_ptr;
   TCPIP_Event_add(&bootp->RESEND);

   if_ptr->BOOT = (pointer)parms;

} /* Endbody */
Beispiel #10
0
void NAT_close_internal
   (
      NAT_PARM_PTR   parm_ptr    /* [IN] Unused */         
   )
{ /* Body */
   NAT_CFG_STRUCT_PTR      nat_cfg_ptr = RTCS_getcfg(NAT);
   uint_32                 error;
   
   if (nat_cfg_ptr == NULL) {
      error = RTCSERR_NAT_NOT_INITIALIZED;
   } else {
      nat_cfg_ptr->NAT_EXEC = NULL;
      error = RTCS_OK;
   }

   RTCSCMD_complete(parm_ptr, error);         
} /* Endbody */
Beispiel #11
0
void DNAT_add_rule_internal
   (
      DNAT_PARM_PTR           dparm_ptr      /* [IN] */   
   )
{ /* Body */
   NAT_CFG_STRUCT_PTR         nat_cfg_ptr = RTCS_getcfg(NAT);
   DNAT_ELEMENT_STRUCT_PTR    new_element_ptr, prev_element_ptr, next_element_ptr;

   if (nat_cfg_ptr == NULL) {
      RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_NOT_INITIALIZED);
      return;
   }

   if (! NAT_is_private_addr(&nat_cfg_ptr->PRIVATE_NETWORKS,dparm_ptr->RULE.PRIVATE_IP)) {
      RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_INVALID_PRIVATE_ADDRESS);
      return;
   }

   if (IP_is_local(NULL, dparm_ptr->RULE.PRIVATE_IP)) {
      RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_INVALID_PRIVATE_ADDRESS);
      return;
   }
        
   prev_element_ptr = NULL;
   next_element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_head(&nat_cfg_ptr->RULE_QUEUE);  
   
   while ((next_element_ptr != NULL) && 
          (next_element_ptr->RULE.PRIORITY > dparm_ptr->RULE.PRIORITY)) {
      prev_element_ptr = next_element_ptr;
      next_element_ptr = (DNAT_ELEMENT_STRUCT_PTR) 
         _queue_next(&nat_cfg_ptr->RULE_QUEUE, &prev_element_ptr->ELEMENT);
   }
   
   if (next_element_ptr != NULL) {
      if (next_element_ptr->RULE.PRIORITY == dparm_ptr->RULE.PRIORITY) {
         // A rule of the given priority exist
         RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_DUPLICATE_PRIORITY);
         return;
      }
   }

   new_element_ptr = (DNAT_ELEMENT_STRUCT_PTR)_mem_alloc_system_zero(sizeof(DNAT_ELEMENT_STRUCT));

   if (new_element_ptr == NULL) {
      RTCSCMD_complete(dparm_ptr, RTCSERR_OUT_OF_MEMORY);
      return;
   } /* Endif */

   new_element_ptr->RULE    = dparm_ptr->RULE;

   _queue_insert(&nat_cfg_ptr->RULE_QUEUE, &prev_element_ptr->ELEMENT, &new_element_ptr->ELEMENT);    
   RTCSCMD_complete(dparm_ptr, RTCS_OK);
}/* Endbody */
Beispiel #12
0
void TCP_Close_TCB
   (
      TCB_STRUCT_PTR       tcb,     /* IN/OUT - TCP context */
      int_32               errnum,  /* IN     - error code to return */
      TCP_CFG_STRUCT_PTR   tcp_cfg  /* IN/OUT - TCP layer data */
   )
{ /* Body */
   TCP_PARM_PTR      req;
   SbufNode _PTR_    buf;
   boolean           first = TRUE;  /* for returning Sends */
   boolean           not_syn_recv = (tcb->state != SYN_RECEIVED);

   /*
   ** This prevents new packets from being queued on this TCB;
   **   however there might still be some queued (but only if
   **   there are no outstanding Receive requests).
   */
   tcb->state = CLOSED;

   /*
   ** Cancel timers...
   */
   (void)TCP_Timer_stop(&tcb->sndxmittq.t, tcp_cfg->qhead);
   (void)TCP_Timer_stop(&tcb->sndacktq.t, tcp_cfg->qhead);
   (void)TCP_Timer_stop(&tcb->sndtq.t, tcp_cfg->qhead);
   (void)TCP_Timer_stop(&tcb->rcvtq.t, tcp_cfg->qhead);

   /*
   ** Return open request if there is one.  This should
   ** only happen if we are closing on error.
   */
   if ( errnum != RTCS_OK && not_syn_recv) {
      TCP_Return_open(tcb, errnum, tcp_cfg);
   } /* Endif */

   /*
   ** Terminate any Receive requests.  We can't receive any more
   **    packets in the CLOSED state, and presence of any Receives
   **    means that all data that could be (contiguously) in the
   **    first Receive is already there (see TCP_Process_data).
   **
   ** In this case the TCB could actually be released, but wait for
   **    user to close it.  Don't have to delete all of the RcvChunks
   **    or indicate no data left in ring since a TCP_Process_close or
   **    TCP_Process_receive will do this.
   */
   while ( tcb->rcvHead != NULL ) {

      TCP_Reply_receive(tcb, tcp_cfg, errnum);
      if ( tcb->rcvHead != NULL ) {
         TCP_Setup_receive(tcb->rcvHead, tcb, tcp_cfg);
      } /* Endif */

   } /* Endwhile */

   /*
   ** Terminate any Send requests
   */
   buf = tcb->sndbuf;
   while ( buf != NULL ) {

      tcb->sndbuf = buf->next;
      if ( tcb->sndbuf == NULL ) {
         tcb->sndbuftail = NULL;
      } /* Endif */

      req = buf->req;
      if ( req != NULL ) {

         /* report actual amount sent */
         if ( first ) {
            req->BUFF_LENG  = tcb->snduna - tcb->sndbufseq;
         } else {
            req->BUFF_LENG = 0;
         } /* Endif */
         RTCSCMD_complete(req, errnum);

      } /* Endif */
      first = FALSE;

      _mem_free(buf);
      buf = tcb->sndbuf;

   } /* Endwhile */


   /*  Terminate any wait request
    */
#if 0
   req = tcb->oclient;
   if ( req != NULL ) {

      req->STATUS     = tcb->status;
      req->SOFTERROR  = tcb->lasterror;
      RTCSCMD_complete(req, errnum);
      tcb->oclient    = NULL;

   } /* Endif */
#endif

   /*
   ** Notify socket layer in case some task is blocked on select()
   ** waiting for data on this socket.
   */
   SOCK_select_signal(tcb->SOCKET, tcb->state);   

   /*  Delete send buffers (keep receive buffer in case there is
    *  pending data)
    */
   if ( tcb->sndringbuf != NULL ) {
      _mem_free(tcb->sndringbuf);
   } /* Endif */
   tcb->sndringbuf = NULL;

   if ( tcb->sndclk != NULL ) {
      _mem_free(tcb->sndclk);     /* xmit timestamps buffer */
   } /* Endif */
   tcb->sndclk = NULL;

} /* Endbody */
Beispiel #13
0
// Start CR 2316
static boolean RTCSMIB_request_internal
   (
      RTCSMIB_WALK_PTR  mib
   )
{ /* Body */
   uchar_ptr inbuffer, nextvar,checkbuffer;
   uint_32 inbuf_length, nextlength,check_length;
   uint_32 varlen;
   boolean  ok = FALSE;
   uint_32  index =0;
   uint_32  errstat =0;
   uint_32 error_index;

   mib->errstat = SNMP_ERROR_noError;

   switch (mib->pdutype) {
   case ASN1_TYPE_PDU_GET:
      ok = RTCSMIB_get(mib);
      break;
   case ASN1_TYPE_PDU_GETNEXT:
      ok = RTCSMIB_powerful_getnext(mib);
      break;
   case ASN1_TYPE_PDU_SET:
        inbuffer = mib->inbuf;   
        inbuf_length = mib->inlen;
        
        checkbuffer = inbuffer;
        check_length = inbuf_length;
        
        error_index =0;
        
        //check first to ensure all variables in set request are valid
        if (check_length >= 5)  /* Minmum length for a set operation is 5 */
        {
            ASN1_READ_TYPELEN_EXPECT(mib, ASN1_TYPE_SEQUENCE, varlen);
            nextvar = (uchar_ptr) (mib->inbuf + varlen);
            nextlength = check_length - ((uint_32)(nextvar - checkbuffer));
            mib->inbuf = checkbuffer;
            mib->inlen = check_length; 
            mib->errstat = SNMP_ERROR_noError;
            ok = RTCSMIB_check(mib);
            index++;
            if(mib->errstat)
            {
              errstat = mib->errstat;
              error_index = index;
            }
            mib->inbuf = nextvar;
            checkbuffer = nextvar;
            mib->inlen = nextlength;
            check_length = nextlength;
        }
        
        if(error_index) //invalid variable in set request,stop set operation to all variables 
        {
           mib->errstat = errstat;
           break;
        }
        
        mib->inbuf = inbuffer;
        mib->inlen = inbuf_length;
        
        //all variables are valid, so set beginning
        if (inbuf_length >= 5)  /* Minmum length for a set operation is 5 */
        {
            ASN1_READ_TYPELEN_EXPECT(mib, ASN1_TYPE_SEQUENCE, varlen);
            nextvar = (uchar_ptr) (mib->inbuf + varlen);
            nextlength = inbuf_length - ((uint_32)(nextvar - inbuffer));
            mib->inbuf = inbuffer;
            mib->inlen = inbuf_length; 
            ok = RTCSMIB_set(mib);
            mib->inbuf = nextvar;
            inbuffer = nextvar;
            mib->inlen = nextlength;
            inbuf_length = nextlength;
        } /* Endwhile */
      break;
   } /* Endswitch */

   if (!ok && !mib->errstat) {
      mib->errstat = SNMP_ERROR_PARSE;
   } /* Endif */

/* Start CR 2162 */
#ifndef TRAVERSE_MIB_IN_SNMP_TASK
   RTCSCMD_complete(mib, RTCS_OK);
#endif
/* End CR 2162 */
return (ok);
} /* Endbody */
Beispiel #14
0
void SOCK_select
   (
      SOCKSELECT_PARM_PTR  parms
   )
{ /* Body */
   uint_32 _PTR_  socket_array;
   int i, i2;
   uint_32 fds[RTCS_SELECT_MAX_FDS];
   int active = FALSE;
   
   // param check
   if ((parms->sock_count != 0 && parms->sock_ptr == NULL) || (parms->writesock_count != 0 && parms->writesock_ptr == NULL)) {
      RTCSCMD_complete(parms, RTCSERR_INVALID_PARAMETER);
      return;   
   }

   // read fds - check every socket in the supplied array
   if (parms->sock_count) {
      _mem_zero(fds, parms->sock_count * sizeof(uint_32));   
      for (i = 0, i2 = 0; i < parms->sock_count; i++) {
         if (SOCK_select_activity((SOCKET_STRUCT_PTR)parms->sock_ptr[i], 0)) {
            fds[i2++] = parms->sock_ptr[i];
         }
      }
   
      // update socket array - only active sockets
      if (i2) {
         _mem_zero(parms->sock_ptr, parms->sock_count * sizeof(uint_32));
         _mem_copy(fds, parms->sock_ptr, i2 * sizeof(uint_32));
         parms->sock_count = i2;
         parms->sock = fds[0];

         active = TRUE;
      }
   }
   
   // write fds - check every socket in the supplied array
   if (parms->writesock_count) {
      _mem_zero(fds, parms->writesock_count * sizeof(uint_32));
      for (i = 0, i2 = 0; i < parms->writesock_count; i++) {
         if (SOCK_select_activity((SOCKET_STRUCT_PTR)parms->writesock_ptr[i], 1)) {
            fds[i2++] = parms->writesock_ptr[i];
         }
      }

      // update socket array - only active sockets
      if (i2) {
         _mem_zero(parms->writesock_ptr, parms->writesock_count * sizeof(uint_32));
         _mem_copy(fds, parms->writesock_ptr, i2 * sizeof(uint_32));
         parms->writesock_count = i2;
      
         if (active == FALSE) {
            // write fds active but read fds no - set read fds to zero
            _mem_zero(parms->sock_ptr, parms->sock_count * sizeof(uint_32));
            parms->sock_count = 0;
            parms->sock = fds[0];
         }
      
         active = TRUE;
      }
      else if (active == TRUE) {
         // read fds active but write fds no - set write fds to zero
         _mem_zero(parms->writesock_ptr, parms->writesock_count * sizeof(uint_32));
         parms->writesock_count = 0;
      }
   }

   if (active == TRUE) {
      // some fds active
      RTCSCMD_complete(parms, RTCS_OK);
      return;
   }

   if (parms->timeout == (uint_32)-1) {
      parms->sock = 0;
      RTCSCMD_complete(parms, RTCS_OK);
      return;
   } /* Endif */

   parms->owner = 0;
   SOCK_select_block(parms);

} /* Endbody */
Beispiel #15
0
/*FUNCTION*-------------------------------------------------------------
*
* Function Name   : ICMP6_send_echo
* Parameters      :
*
*     _ip_address       ipaddress   [IN] destination IP address
*     uint_32           timeout     [IN/OUT] timeout/rtt
*     uint_16           id          [IN] identification for echo message.
*     uint_16           seq         not used
*
* Comments        :
*     Send an ICMP Echo Request packet.
*
*END*-----------------------------------------------------------------*/
void ICMP6_send_echo(ICMP_ECHO_PARAM_PTR     parms)
{

#if RTCSCFG_ENABLE_IP6

   ICMP6_CFG_STRUCT_PTR     ICMP6_cfg_ptr = RTCS_getcfg(ICMP6);
   RTCSPCB_PTR              pcb;
   ICMP6_ECHO_HEADER_PTR    packet;
   _rtcs_if_handle          ihandle_dest = NULL; 
   uint_32                  error;


   IF_ICMP6_STATS_ENABLED(ICMP6_cfg_ptr->STATS.COMMON.ST_TX_TOTAL++);
   parms->seq = ICMP6_cfg_ptr->ECHO_SEQ++;

   pcb = RTCSPCB_alloc_send();
   if (pcb == NULL)
   {
      IF_ICMP6_STATS_ENABLED(ICMP6_cfg_ptr->STATS.COMMON.ST_TX_MISSED++);
      RTCSCMD_complete(parms, RTCSERR_PCB_ALLOC);
      return;
   } 
        
    if(parms->ping_param->data_buffer && parms->ping_param->data_buffer_size)
    {
        error = RTCSPCB_append_fragment(pcb, parms->ping_param->data_buffer_size, parms->ping_param->data_buffer);
        if (error) 
        {
            IF_ICMP6_STATS_ENABLED(ICMP6_cfg_ptr->STATS.COMMON.ST_TX_ERRORS++);
            RTCSLOG_PCB_FREE(pcb, error);
            RTCSPCB_free(pcb);
            RTCSCMD_complete(parms, error);
            return;
        }
   }

   error = RTCSPCB_insert_header(pcb, sizeof(ICMP6_ECHO_HEADER));
   if (error)
   {
      IF_ICMP6_STATS_ENABLED(ICMP6_cfg_ptr->STATS.COMMON.ST_TX_ERRORS++);
      IF_ICMP6_STATS_ENABLED(RTCS_seterror(&ICMP6_cfg_ptr->STATS.ERR_TX, error, (uint_32)pcb));
      RTCSLOG_PCB_FREE(pcb, error);
      RTCSPCB_free(pcb);
      RTCSCMD_complete(parms, error);
      return;
   } 

   RTCSLOG_PCB_WRITE(pcb, RTCS_LOGCTRL_PROTO(IPPROTO_ICMPV6), 0);

   packet = (ICMP6_ECHO_HEADER_PTR)RTCSPCB_DATA(pcb);
   pcb->TRANSPORT_LAYER = (uchar_ptr)packet;
   htonc(packet->HEAD.TYPE, ICMP6_TYPE_ECHO_REQ);
   htonc(packet->HEAD.CODE, 0);
   htons(packet->HEAD.CHECKSUM, 0);
   htons(packet->ID,  parms->ping_param->id);
   htons(packet->SEQ, parms->seq);

   pcb->IP_SUM     = IP_Sum_PCB(RTCSPCB_SIZE(pcb), pcb);
   pcb->IP_SUM_PTR = packet->HEAD.CHECKSUM;
  
   if(((sockaddr_in6 *)(&parms->ping_param->addr))->sin6_scope_id)
   {
        ihandle_dest = ip6_if_get_by_scope_id(((sockaddr_in6 *)(&parms->ping_param->addr))->sin6_scope_id);
   }

   parms->EXPIRE.TIME    = parms->ping_param->timeout;
   parms->EXPIRE.EVENT   = ICMP6_expire_echo;
   parms->EXPIRE.PRIVATE = parms;
   parms->start_time = RTCS_time_get();   /* get timestamp */

   error = IP6_send(pcb, IPPROTO_ICMPV6|IPTTL(parms->ping_param->hop_limit), NULL/*ipsrc*/, &((sockaddr_in6 *)(&parms->ping_param->addr))->sin6_addr/*ipdest*/, ihandle_dest, 0);


   if (error != RTCS_OK)
   {
      IF_ICMP6_STATS_ENABLED(ICMP6_cfg_ptr->STATS.COMMON.ST_TX_MISSED++);
      RTCSCMD_complete(parms, error);
      return;
   }

   /*
   ** If there is no error add the parm struct to config struct
   ** and initiate the event timer
   */

   IF_ICMP6_STATS_ENABLED(ICMP6_cfg_ptr->STATS.ST_TX_ECHO_REQ++);

   /* add the prameter structure to ICMP  cfg */
   parms->NEXT = ICMP6_cfg_ptr->ECHO_PARAM_HEAD;
   if (parms->NEXT)
   {
      parms->NEXT->PREV = &parms->NEXT;
   } /* Endif */
   ICMP6_cfg_ptr->ECHO_PARAM_HEAD = parms;
   parms->PREV = &ICMP6_cfg_ptr->ECHO_PARAM_HEAD;

   TCPIP_Event_add(&parms->EXPIRE);

#else
    RTCSCMD_complete(parms, RTCSERR_IP_IS_DISABLED);
#endif /* RTCSCFG_ENABLE_IP6 */
}
Beispiel #16
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 */
Beispiel #17
0
void TCP_Process_abort
   (
      TCP_PARM_PTR   req_ptr     /* IN/OUT - the open request */
   )
{ /* Body */
   TCP_CFG_STRUCT_PTR   tcp_cfg;
   TCB_STRUCT_PTR       tcb;
   int_32               reply = RTCS_OK;

   tcp_cfg = RTCS_getcfg(TCP);
   tcb = req_ptr->TCB_PTR;

   if ( tcb == NULL ) { 
      RTCSCMD_complete(req_ptr, RTCSERR_TCP_CONN_RLSD);
      return;
   } 

   IF_TCP_STATS_ENABLED(tcp_cfg->STATS.ST_CONN_ABORTS++);

   if ( tcb->VALID != TCB_VALID_ID ) {
      reply = RTCSERR_TCP_CONN_RLSD;

   } else {

      switch ( tcb->state ) {

         case LISTEN:
            /*
            ** allows for shutdown of listening socket with ABORT option set.
            */
            TCP_Close_TCB(tcb, RTCS_OK, tcp_cfg);
            TCP_Process_release(tcb, tcp_cfg);
            break;

         case SYN_RECEIVED:
         case ESTABLISHED:
         case FINWAIT_1:
         case FINWAIT_2:
         case CLOSE_WAIT:
            TCP_Send_reset(tcb, tcp_cfg);      /* send reset packet */
            /*FALLTHROUGH*/

         case SYN_SENT:
         case CLOSING:
         case LAST_ACK:
         case TIME_WAIT:
            TCP_Close_TCB(tcb, RTCSERR_TCP_CONN_ABORTED, tcp_cfg);
            /*FALLTHROUGH*/

         case BOUND:
         case CLOSED:
            TCP_Process_release(tcb, tcp_cfg);
            break;

         default:
            reply = RTCSERR_TCP_NOT_CONN;
            break;

      } /* End Switch */

   } /* Endif */

   /* The socket will be freed as soon as we return to shutdown() */
   if (tcb->VALID == TCB_VALID_ID) {
      /* Following code no longer needed, as the option is propagated to the TCB when set */ 
      tcb->SOCKET = 0;
   } /* Endif */

   RTCSCMD_complete(req_ptr, reply);

} /* Endbody */
Beispiel #18
0
void BOOTP_service
   (
      RTCSPCB_PTR    rtcs_pcb     /* [IN] BOOTREPLY packet */
   )
{ /* Body */
   IP_IF_PTR               if_ptr = (IP_IF_PTR)rtcs_pcb->IFSRC;
   TCPIP_PARM_BOOTP _PTR_  parms = (TCPIP_PARM_BOOTP _PTR_)if_ptr->BOOT;
   BOOTP_CFG_PTR           bootp = (BOOTP_CFG_PTR) &parms->config;
   BOOTP_PACKET_PTR        bootreply;
   IPIF_PARM               parms_bind;
   uint_32                 error;

   uchar_ptr   opt;
   uchar       len, optval, optlen;

   /* Make sure the datagram is large enough */
   bootreply = (BOOTP_PACKET_PTR)RTCSPCB_DATA(rtcs_pcb);
   if (RTCSPCB_SIZE(rtcs_pcb) < sizeof(BOOTP_PACKET)) {
      RTCSLOG_PCB_FREE(rtcs_pcb, RTCS_OK);
      RTCSPCB_free(rtcs_pcb);
      return;
   } /* Endif */

   /* Make sure the XID matches */
   if (ntohl(bootreply->HEAD.XID) != bootp->XID) {
      RTCSLOG_PCB_FREE(rtcs_pcb, RTCS_OK);
      RTCSPCB_free(rtcs_pcb);
      return;
   } /* Endif */

   RTCSLOG_PCB_READ(rtcs_pcb, RTCS_LOGCTRL_PORT(IPPORT_BOOTPC), 0);

   /* OK, assume this reply is for us */
   BOOTP_close(if_ptr);

   /* Get our IP address, and pick the default netmask */
   parms_bind.ihandle = if_ptr;
   parms_bind.address = ntohl(bootreply->HEAD.YIADDR);
   parms_bind.locmask = 0xFFFFFFFFL;
   parms_bind.netmask = IN_DEFAULT_NET(parms_bind.address);
   parms_bind.probe = FALSE;

   parms->data->SADDR = ntohl(bootreply->HEAD.SIADDR);
#if RTCSCFG_BOOTP_RETURN_YIADDR
   parms->data->CLIENTADDR = ntohl(bootreply->HEAD.YIADDR);
#endif
   _mem_copy(bootreply->DATA.SNAME, parms->data->SNAME, sizeof(BOOTP_DATA));
   RTCSLOG_PCB_FREE(rtcs_pcb, RTCS_OK);
   RTCSPCB_free(rtcs_pcb);

   /* Parse the vend field for recognized options */
   opt = parms->data->OPTIONS;
   len = sizeof(parms->data->OPTIONS);
   if (ntohl(opt) == BOOTP_MAGIC) {
      opt += 4;
      len -= 4;

#define BOOTP_NEXTOPT   opt += optlen; \
                        break

      while (len) {

         /* Get the next option code */
         optval = ntohc(opt);
         opt++;
         len--;

         /* Interpret the pad and end options */
         if (optval == BOOTPOPT_END) break;
         if (optval == BOOTPOPT_PAD) continue;

         /* All other codes have a length byte */
         if (len == 0) break;
         optlen = ntohc(opt);
         opt++;
         len--;
         if (len < optlen) break;
         len -= optlen;

         switch (optval) {

         case BOOTPOPT_MASK:
            if (optlen != 4) {BOOTP_NEXTOPT;}
            parms_bind.netmask = ntohl(opt);
            opt += 4;
            break;

         default:
            BOOTP_NEXTOPT;
         } /* Endswitch */

      } /* Endwhile */
   } /* Endif */

   /* Bind the received IP address to this interface */
   error = RTCSCMD_internal(parms_bind, IPIF_bind);

   /* Done -- unblock the application */
   RTCSCMD_complete(parms, error);

} /* Endbody */
Beispiel #19
0
void TCP_Process_close
   (
      TCP_PARM_PTR   req_ptr     /* IN/OUT - the open request */
   )
{ /* Body */
   TCP_CFG_STRUCT_PTR   tcp_cfg;
   TCB_STRUCT_PTR       tcb;
   int_32               reply = RTCS_OK;

   tcp_cfg = RTCS_getcfg(TCP);
   tcb = req_ptr->TCB_PTR;

   if ( tcb == NULL ) { 
      RTCSCMD_complete(req_ptr, RTCSERR_TCP_CONN_RLSD);
      return;
   } 

   IF_TCP_STATS_ENABLED(tcp_cfg->STATS.ST_CONN_CLOSED++);

   if ( tcb->VALID != TCB_VALID_ID ) {
      reply = RTCSERR_TCP_CONN_RLSD;
      RTCS_log_error( ERROR_TCP,
                           RTCSERR_TCP_BAD_STATE_FOR_CLOSE,
                           (uint_32)tcb,
                           (uint_32)tcb->state,
                           1 );

   } else if ( tcb->state == CLOSED ) {

      /* This should be the standard case if the other side aborted. */
      TCP_Process_release(tcb, tcp_cfg);

   } else if ( (tcb->status & TCPS_FINTOSEND) != 0 ) {

      /* Upper layer must have already given us a tcpCLOSE, so we
       *    can generate an error here. */
      reply = RTCSERR_TCP_CONN_CLOSING;

   } else {

      switch ( tcb->state ) {

         case LISTEN:
         case SYN_SENT:
            TCP_Close_TCB(tcb, RTCS_OK, tcp_cfg);
          case BOUND:
            TCP_Process_release(tcb, tcp_cfg);
            break;

         case SYN_RECEIVED:
            /* no data has been sent */

         case ESTABLISHED:
         case CLOSE_WAIT:

            TCP_Event(tcb,TCPS_FINTOSEND);

            /*  We can only effectively close if all data has been sent,
             *   allowing us to send a FIN immediately; otherwise closing
             *   is delayed (TCPS_FINTOSEND indicates that connection should
             *   be closed as soon as all data is sent)
             */
            if ( tcb->sndnxt == (tcb->sndbufseq + tcb->sndlen) ) {
               TCP_Process_effective_close(tcb, tcp_cfg);
            } else {
               /*
               **  Have to kick ourselves into sending the outstanding
               **  data or we'll sit here forever if the other side is
               **  just waiting.  This would happen if we send w/o PUSH
               **  just before closing.
               */
               TCP_Must_send_ack(tcb, tcp_cfg);
            } /* Endif */

            break;

         default:
            /*  we shouldn't reach here, but jic...  */
            RTCS_log_error( ERROR_TCP,
                                 RTCSERR_TCP_BAD_STATE_FOR_CLOSE,
                                 (uint_32)tcb,
                                 (uint_32)tcb->state,
                                 2);

            reply = RTCSERR_TCP_NOT_CONN;
            break;

      } /* End Switch */

   } /* Endif */

   /* The socket will be freed as soon as we return to shutdown() */
   if (tcb->VALID == TCB_VALID_ID) {
       tcb->SOCKET = 0;
   } /* Endif */

   RTCSCMD_complete(req_ptr, reply);

} /* Endbody */
Beispiel #20
0
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 */